Differential D17066 Diff 41082 src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php
| Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if ($id) { | ||||
| ->needReviewerStatus(true) | ->needReviewerStatus(true) | ||||
| ->needActiveDiffs(true) | ->needActiveDiffs(true) | ||||
| ->executeOne(); | ->executeOne(); | ||||
| if (!$revision) { | if (!$revision) { | ||||
| throw new ConduitException('ERR_NOT_FOUND'); | throw new ConduitException('ERR_NOT_FOUND'); | ||||
| } | } | ||||
| } else { | } else { | ||||
| $revision = DifferentialRevision::initializeNewRevision($viewer); | $revision = DifferentialRevision::initializeNewRevision($viewer); | ||||
| $revision->attachReviewerStatus(array()); | |||||
| $revision->attachActiveDiff(null); | |||||
| } | } | ||||
| $is_edit = $request->getValue('edit'); | $edit_mode = $request->getValue('edit'); | ||||
| $is_create = ($is_edit == 'create'); | $is_create = ($edit_mode == 'create'); | ||||
| $is_edit = ($edit_mode && !$is_create); | |||||
| $field_list = PhabricatorCustomField::getObjectFields( | $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); | ||||
| $revision, | |||||
| ($is_edit | |||||
| ? DifferentialCustomField::ROLE_COMMITMESSAGEEDIT | |||||
| : DifferentialCustomField::ROLE_COMMITMESSAGE)); | |||||
| $field_list | |||||
| ->setViewer($viewer) | |||||
| ->readFieldsFromStorage($revision); | |||||
| $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); | $custom_storage = $this->loadCustomFieldStorage($viewer, $revision); | ||||
| foreach ($field_list as $field) { | |||||
| $field->setCustomFieldStorage($custom_storage); | |||||
| } | |||||
| // If we're editing the message, remove fields like "Conflicts" and | |||||
| // "git-svn-id" which should not be presented to the user for editing. | |||||
| if ($is_edit) { | if ($is_edit) { | ||||
| $fields = $request->getValue('fields', array()); | foreach ($field_list as $field_key => $field) { | ||||
| foreach ($fields as $field => $value) { | if (!$field->isFieldEditable()) { | ||||
| $custom_field = idx($field_map, $field); | unset($field_list[$field_key]); | ||||
| if (!$custom_field) { | |||||
| // Just ignore this, these workflows don't make strong distictions | |||||
| // about field editability on the client side. | |||||
| continue; | |||||
| } | |||||
| if ($is_create || | |||||
| $custom_field->shouldOverwriteWhenCommitMessageIsEdited()) { | |||||
| $custom_field->readValueFromCommitMessage($value); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| $phids = array(); | $overrides = $request->getValue('fields', array()); | ||||
| foreach ($field_list->getFields() as $key => $field) { | |||||
| $field_phids = $field->getRequiredHandlePHIDsForCommitMessage(); | |||||
| if (!is_array($field_phids)) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Custom field "%s" was expected to return an array of handle '. | |||||
| 'PHIDs required for commit message rendering, but returned "%s" '. | |||||
| 'instead.', | |||||
| $field->getFieldKey(), | |||||
| gettype($field_phids))); | |||||
| } | |||||
| $phids[$key] = $field_phids; | |||||
| } | |||||
| $all_phids = array_mergev($phids); | $value_map = array(); | ||||
| if ($all_phids) { | foreach ($field_list as $field_key => $field) { | ||||
| $all_handles = id(new PhabricatorHandleQuery()) | if (array_key_exists($field_key, $overrides)) { | ||||
| ->setViewer($viewer) | $field_value = $overrides[$field_key]; | ||||
| ->withPHIDs($all_phids) | |||||
| ->execute(); | |||||
| } else { | } else { | ||||
| $all_handles = array(); | $field_value = $field->readFieldValueFromObject($revision); | ||||
| } | |||||
| // We're calling this method on the value no matter where we got it | |||||
| // from, so we hit the same validation logic for values which came over | |||||
| // the wire and which we generated. | |||||
| $field_value = $field->readFieldValueFromConduit($field_value); | |||||
| $value_map[$field_key] = $field_value; | |||||
| } | } | ||||
| $key_title = id(new DifferentialTitleField())->getFieldKey(); | $key_title = DifferentialTitleCommitMessageField::FIELDKEY; | ||||
| $default_title = DifferentialTitleField::getDefaultTitle(); | |||||
| $commit_message = array(); | $commit_message = array(); | ||||
| foreach ($field_list->getFields() as $key => $field) { | foreach ($field_list as $field_key => $field) { | ||||
| $handles = array_select_keys($all_handles, $phids[$key]); | $label = $field->getFieldName(); | ||||
| $wire_value = $value_map[$field_key]; | |||||
| $value = $field->renderFieldValue($wire_value); | |||||
| $label = $field->renderCommitMessageLabel(); | $is_template = ($is_edit && $field->isTemplateField()); | ||||
| $value = $field->renderCommitMessageValue($handles); | |||||
| if (!is_string($value) && !is_null($value)) { | if (!is_string($value) && !is_null($value)) { | ||||
| throw new Exception( | throw new Exception( | ||||
| pht( | pht( | ||||
| 'Custom field "%s" was expected to render a string or null value, '. | 'Commit message field "%s" was expected to render a string or '. | ||||
| 'but rendered a "%s" instead.', | 'null value, but rendered a "%s" instead.', | ||||
| $field->getFieldKey(), | $field->getFieldKey(), | ||||
| gettype($value))); | gettype($value))); | ||||
| } | } | ||||
| $is_title = ($key == $key_title); | $is_title = ($field_key == $key_title); | ||||
| if (!strlen($value)) { | if (!strlen($value)) { | ||||
| if ($is_title) { | if ($is_template) { | ||||
| $commit_message[] = $default_title; | |||||
| } else { | |||||
| if ($is_edit && $field->shouldAppearInCommitMessageTemplate()) { | |||||
| $commit_message[] = $label.': '; | $commit_message[] = $label.': '; | ||||
| } | } | ||||
| } | |||||
| } else { | } else { | ||||
| if ($is_title) { | if ($is_title) { | ||||
| $commit_message[] = $value; | $commit_message[] = $value; | ||||
| } else { | } else { | ||||
| $value = str_replace( | $value = str_replace( | ||||
| array("\r\n", "\r"), | array("\r\n", "\r"), | ||||
| array("\n", "\n"), | array("\n", "\n"), | ||||
| $value); | $value); | ||||
| if (strpos($value, "\n") !== false || substr($value, 0, 2) === ' ') { | if (strpos($value, "\n") !== false || substr($value, 0, 2) === ' ') { | ||||
| $commit_message[] = "{$label}:\n{$value}"; | $commit_message[] = "{$label}:\n{$value}"; | ||||
| } else { | } else { | ||||
| $commit_message[] = "{$label}: {$value}"; | $commit_message[] = "{$label}: {$value}"; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if ($is_edit) { | return implode("\n\n", $commit_message); | ||||
| $tip = $this->getProTip($field_list); | |||||
| if ($tip !== null) { | |||||
| $commit_message[] = "\n".$tip; | |||||
| } | |||||
| } | |||||
| $commit_message = implode("\n\n", $commit_message); | |||||
| return $commit_message; | |||||
| } | } | ||||
| private function getProTip() { | private function loadCustomFieldStorage( | ||||
| // Any field can provide tips, whether it normally appears on commit | PhabricatorUser $viewer, | ||||
| // messages or not. | DifferentialRevision $revision) { | ||||
| $field_list = PhabricatorCustomField::getObjectFields( | $custom_field_list = PhabricatorCustomField::getObjectFields( | ||||
| new DifferentialRevision(), | $revision, | ||||
| PhabricatorCustomField::ROLE_DEFAULT); | DifferentialCustomField::ROLE_COMMITMESSAGE); | ||||
| $custom_field_list | |||||
| ->setViewer($viewer) | |||||
| ->readFieldsFromStorage($revision); | |||||
| $tips = array(); | $custom_field_map = array(); | ||||
| foreach ($field_list->getFields() as $key => $field) { | foreach ($custom_field_list->getFields() as $custom_field) { | ||||
| $tips[] = $field->getProTips(); | if (!$custom_field->shouldUseStorage()) { | ||||
| continue; | |||||
| } | } | ||||
| $tips = array_mergev($tips); | $custom_field_key = $custom_field->getFieldKey(); | ||||
| $custom_field_value = $custom_field->getValueForStorage(); | |||||
| if (!$tips) { | $custom_field_map[$custom_field_key] = $custom_field_value; | ||||
| return null; | |||||
| } | } | ||||
| shuffle($tips); | return $custom_field_map; | ||||
| $tip = pht('Tip: %s', head($tips)); | |||||
| $tip = wordwrap($tip, 78, "\n", true); | |||||
| $lines = explode("\n", $tip); | |||||
| foreach ($lines as $key => $line) { | |||||
| $lines[$key] = '# '.$line; | |||||
| } | } | ||||
| return implode("\n", $lines); | |||||
| } | |||||
| } | } | ||||