getID().'/'; $uri = PhabricatorEnv::getProductionURI($uri); return array( 'id' => $diff->getID(), 'phid' => $diff->getPHID(), 'uri' => $uri, ); } protected function buildInlineInfoDictionary( DifferentialInlineComment $inline, DifferentialChangeset $changeset = null) { $file_path = null; $diff_id = null; if ($changeset) { $file_path = $inline->getIsNewFile() ? $changeset->getFilename() : $changeset->getOldFile(); $diff_id = $changeset->getDiffID(); } return array( 'id' => $inline->getID(), 'authorPHID' => $inline->getAuthorPHID(), 'filePath' => $file_path, 'isNewFile' => $inline->getIsNewFile(), 'lineNumber' => $inline->getLineNumber(), 'lineLength' => $inline->getLineLength(), 'diffID' => $diff_id, 'content' => $inline->getContent(), ); } protected function applyFieldEdit( ConduitAPIRequest $request, DifferentialRevision $revision, DifferentialDiff $diff, array $fields, $message) { $viewer = $request->getUser(); // We're going to build the body of a "differential.revision.edit" API // request, then just call that code directly. $xactions = array(); $xactions[] = array( 'type' => DifferentialRevisionEditEngine::KEY_UPDATE, 'value' => $diff->getPHID(), ); $field_map = DifferentialCommitMessageField::newEnabledFields($viewer); $values = $request->getValue('fields', array()); foreach ($values as $key => $value) { $field = idx($field_map, $key); if (!$field) { // NOTE: We're just ignoring fields we don't know about. This isn't // ideal, but the way the workflow currently works involves us getting // several read-only fields, like the revision ID field, which we should // just skip. continue; } // The transaction itself will be validated so this is somewhat // redundant, but this validator will sometimes give us a better error // message or a better reaction to a bad value type. $value = $field->readFieldValueFromConduit($value); foreach ($field->getFieldTransactions($value) as $xaction) { $xactions[] = $xaction; } } $message = $request->getValue('message'); if (strlen($message)) { // This is a little awkward, and should move elsewhere or be removed. It // largely exists for legacy reasons. See some discussion in T7899. $first_line = head(phutil_split_lines($message, false)); $first_line = id(new PhutilUTF8StringTruncator()) ->setMaximumBytes(250) ->setMaximumGlyphs(80) ->truncateString($first_line); $diff->setDescription($first_line); $diff->save(); $xactions[] = array( 'type' => PhabricatorCommentEditEngineExtension::EDITKEY, 'value' => $message, ); } $method = 'differential.revision.edit'; $params = array( 'transactions' => $xactions, ); if ($revision->getID()) { $params['objectIdentifier'] = $revision->getID(); } return id(new ConduitCall($method, $params, $strict = true)) ->setUser($viewer) ->execute(); } protected function loadCustomFieldsForRevisions( PhabricatorUser $viewer, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); if (!$revisions) { return array(); } $field_lists = array(); foreach ($revisions as $revision) { $revision_phid = $revision->getPHID(); $field_list = PhabricatorCustomField::getObjectFields( $revision, PhabricatorCustomField::ROLE_CONDUIT); $field_list ->setViewer($viewer) ->readFieldsFromObject($revision); $field_lists[$revision_phid] = $field_list; } $all_fields = array(); foreach ($field_lists as $field_list) { foreach ($field_list->getFields() as $field) { $all_fields[] = $field; } } id(new PhabricatorCustomFieldStorageQuery()) ->addFields($all_fields) ->execute(); $results = array(); foreach ($field_lists as $revision_phid => $field_list) { $results[$revision_phid] = array(); foreach ($field_list->getFields() as $field) { $field_key = $field->getFieldKeyForConduit(); $value = $field->getConduitDictionaryValue(); $results[$revision_phid][$field_key] = $value; } } // For compatibility, fill in these "custom fields" by querying for them // efficiently. See T11404 for discussion. $legacy_edge_map = array( 'phabricator:projects' => PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, 'phabricator:depends-on' => DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST, ); $query = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array_keys($results)) ->withEdgeTypes($legacy_edge_map); $query->execute(); foreach ($results as $revision_phid => $dict) { foreach ($legacy_edge_map as $edge_key => $edge_type) { $phid_list = $query->getDestinationPHIDs( array($revision_phid), array($edge_type)); $results[$revision_phid][$edge_key] = $phid_list; } } return $results; } }