[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/conduit/ -> DifferentialGetCommitMessageConduitAPIMethod.php (source)

   1  <?php
   2  
   3  final class DifferentialGetCommitMessageConduitAPIMethod
   4    extends DifferentialConduitAPIMethod {
   5  
   6    public function getAPIMethodName() {
   7      return 'differential.getcommitmessage';
   8    }
   9  
  10    public function getMethodDescription() {
  11      return 'Retrieve Differential commit messages or message templates.';
  12    }
  13  
  14    public function defineParamTypes() {
  15      $edit_types = array('edit', 'create');
  16  
  17      return array(
  18        'revision_id' => 'optional revision_id',
  19        'fields' => 'optional dict<string, wild>',
  20        'edit' => 'optional '.$this->formatStringConstants($edit_types),
  21      );
  22    }
  23  
  24    public function defineReturnType() {
  25      return 'nonempty string';
  26    }
  27  
  28    public function defineErrorTypes() {
  29      return array(
  30        'ERR_NOT_FOUND' => 'Revision was not found.',
  31      );
  32    }
  33  
  34    protected function execute(ConduitAPIRequest $request) {
  35      $id = $request->getValue('revision_id');
  36      $viewer = $request->getUser();
  37  
  38      if ($id) {
  39        $revision = id(new DifferentialRevisionQuery())
  40          ->withIDs(array($id))
  41          ->setViewer($viewer)
  42          ->needReviewerStatus(true)
  43          ->needActiveDiffs(true)
  44          ->executeOne();
  45        if (!$revision) {
  46          throw new ConduitException('ERR_NOT_FOUND');
  47        }
  48      } else {
  49        $revision = DifferentialRevision::initializeNewRevision($viewer);
  50        $revision->attachReviewerStatus(array());
  51        $revision->attachActiveDiff(null);
  52      }
  53  
  54      $is_edit = $request->getValue('edit');
  55      $is_create = ($is_edit == 'create');
  56  
  57      $field_list = PhabricatorCustomField::getObjectFields(
  58        $revision,
  59        ($is_edit
  60          ? DifferentialCustomField::ROLE_COMMITMESSAGEEDIT
  61          : DifferentialCustomField::ROLE_COMMITMESSAGE));
  62  
  63      $field_list
  64        ->setViewer($viewer)
  65        ->readFieldsFromStorage($revision);
  66  
  67      $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit');
  68  
  69      if ($is_edit) {
  70        $fields = $request->getValue('fields', array());
  71        foreach ($fields as $field => $value) {
  72          $custom_field = idx($field_map, $field);
  73          if (!$custom_field) {
  74            // Just ignore this, these workflows don't make strong distictions
  75            // about field editability on the client side.
  76            continue;
  77          }
  78          if ($is_create ||
  79              $custom_field->shouldOverwriteWhenCommitMessageIsEdited()) {
  80            $custom_field->readValueFromCommitMessage($value);
  81          }
  82        }
  83      }
  84  
  85      $phids = array();
  86      foreach ($field_list->getFields() as $key => $field) {
  87        $field_phids = $field->getRequiredHandlePHIDsForCommitMessage();
  88        if (!is_array($field_phids)) {
  89          throw new Exception(
  90            pht(
  91              'Custom field "%s" was expected to return an array of handle '.
  92              'PHIDs required for commit message rendering, but returned "%s" '.
  93              'instead.',
  94              $field->getFieldKey(),
  95              gettype($field_phids)));
  96        }
  97        $phids[$key] = $field_phids;
  98      }
  99  
 100      $all_phids = array_mergev($phids);
 101      if ($all_phids) {
 102        $all_handles = id(new PhabricatorHandleQuery())
 103          ->setViewer($viewer)
 104          ->withPHIDs($all_phids)
 105          ->execute();
 106      } else {
 107        $all_handles = array();
 108      }
 109  
 110      $key_title = id(new DifferentialTitleField())->getFieldKey();
 111      $default_title = DifferentialTitleField::getDefaultTitle();
 112  
 113      $commit_message = array();
 114      foreach ($field_list->getFields() as $key => $field) {
 115        $handles = array_select_keys($all_handles, $phids[$key]);
 116  
 117        $label = $field->renderCommitMessageLabel();
 118        $value = $field->renderCommitMessageValue($handles);
 119  
 120        if (!is_string($value) && !is_null($value)) {
 121          throw new Exception(
 122            pht(
 123              'Custom field "%s" was expected to render a string or null value, '.
 124              'but rendered a "%s" instead.',
 125              $field->getFieldKey(),
 126              gettype($value)));
 127        }
 128  
 129        $is_title = ($key == $key_title);
 130  
 131        if (!strlen($value)) {
 132          if ($is_title) {
 133            $commit_message[] = $default_title;
 134          } else {
 135            if ($is_edit && $field->shouldAppearInCommitMessageTemplate()) {
 136              $commit_message[] = $label.': ';
 137            }
 138          }
 139        } else {
 140          if ($is_title) {
 141            $commit_message[] = $value;
 142          } else {
 143            $value = str_replace(
 144              array("\r\n", "\r"),
 145              array("\n",   "\n"),
 146              $value);
 147            if (strpos($value, "\n") !== false || substr($value, 0, 2) === '  ') {
 148              $commit_message[] = "{$label}:\n{$value}";
 149            } else {
 150              $commit_message[] = "{$label}: {$value}";
 151            }
 152          }
 153        }
 154      }
 155  
 156      if ($is_edit) {
 157        $tip = $this->getProTip($field_list);
 158        if ($tip !== null) {
 159          $commit_message[] = "\n".$tip;
 160        }
 161      }
 162  
 163      $commit_message = implode("\n\n", $commit_message);
 164  
 165      return $commit_message;
 166    }
 167  
 168    private function getProTip() {
 169      // Any field can provide tips, whether it normally appears on commit
 170      // messages or not.
 171      $field_list = PhabricatorCustomField::getObjectFields(
 172        new DifferentialRevision(),
 173        PhabricatorCustomField::ROLE_DEFAULT);
 174  
 175      $tips = array();
 176      foreach ($field_list->getFields() as $key => $field) {
 177        $tips[] = $field->getProTips();
 178      }
 179      $tips = array_mergev($tips);
 180  
 181      if (!$tips) {
 182        return null;
 183      }
 184  
 185      shuffle($tips);
 186  
 187      $tip = pht('Tip: %s', head($tips));
 188      $tip = wordwrap($tip, 78, "\n", true);
 189  
 190      $lines = explode("\n", $tip);
 191      foreach ($lines as $key => $line) {
 192        $lines[$key] = '# '.$line;
 193      }
 194  
 195      return implode("\n", $lines);
 196    }
 197  
 198  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1