[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/customfield/ -> DifferentialJIRAIssuesField.php (source)

   1  <?php
   2  
   3  final class DifferentialJIRAIssuesField
   4    extends DifferentialStoredCustomField {
   5  
   6    private $error;
   7  
   8    public function getFieldKey() {
   9      return 'phabricator:jira-issues';
  10    }
  11  
  12    public function getFieldKeyForConduit() {
  13      return 'jira.issues';
  14    }
  15  
  16    public function isFieldEnabled() {
  17      return (bool)PhabricatorJIRAAuthProvider::getJIRAProvider();
  18    }
  19  
  20    public function canDisableField() {
  21      return false;
  22    }
  23  
  24    public function getValueForStorage() {
  25      return json_encode($this->getValue());
  26    }
  27  
  28    public function setValueFromStorage($value) {
  29      try {
  30        $this->setValue(phutil_json_decode($value));
  31      } catch (PhutilJSONParserException $ex) {
  32        $this->setValue(array());
  33      }
  34      return $this;
  35    }
  36  
  37    public function getFieldName() {
  38      return pht('JIRA Issues');
  39    }
  40  
  41    public function getFieldDescription() {
  42      return pht('Lists associated JIRA issues.');
  43    }
  44  
  45    public function shouldAppearInPropertyView() {
  46      return true;
  47    }
  48  
  49    public function renderPropertyViewLabel() {
  50      return $this->getFieldName();
  51    }
  52  
  53    public function renderPropertyViewValue(array $handles) {
  54      $xobjs = $this->loadDoorkeeperExternalObjects($this->getValue());
  55      if (!$xobjs) {
  56        return null;
  57      }
  58  
  59      $links = array();
  60      foreach ($xobjs as $xobj) {
  61        $links[] = id(new DoorkeeperTagView())
  62          ->setExternalObject($xobj);
  63      }
  64  
  65      return phutil_implode_html(phutil_tag('br'), $links);
  66    }
  67  
  68    private function buildDoorkeeperRefs($value) {
  69      $provider = PhabricatorJIRAAuthProvider::getJIRAProvider();
  70  
  71      $refs = array();
  72      if ($value) {
  73        foreach ($value as $jira_key) {
  74          $refs[] = id(new DoorkeeperObjectRef())
  75            ->setApplicationType(DoorkeeperBridgeJIRA::APPTYPE_JIRA)
  76            ->setApplicationDomain($provider->getProviderDomain())
  77            ->setObjectType(DoorkeeperBridgeJIRA::OBJTYPE_ISSUE)
  78            ->setObjectID($jira_key);
  79        }
  80      }
  81  
  82      return $refs;
  83    }
  84  
  85    private function loadDoorkeeperExternalObjects($value) {
  86      $refs = $this->buildDoorkeeperRefs($value);
  87      if (!$refs) {
  88        return array();
  89      }
  90  
  91      $xobjs = id(new DoorkeeperExternalObjectQuery())
  92        ->setViewer($this->getViewer())
  93        ->withObjectKeys(mpull($refs, 'getObjectKey'))
  94        ->execute();
  95  
  96      return $xobjs;
  97    }
  98  
  99    public function shouldAppearInEditView() {
 100      return PhabricatorJIRAAuthProvider::getJIRAProvider();
 101    }
 102  
 103    public function shouldAppearInApplicationTransactions() {
 104      return PhabricatorJIRAAuthProvider::getJIRAProvider();
 105    }
 106  
 107    public function readValueFromRequest(AphrontRequest $request) {
 108      $this->setValue($request->getStrList($this->getFieldKey()));
 109      return $this;
 110    }
 111  
 112    public function renderEditControl(array $handles) {
 113      return id(new AphrontFormTextControl())
 114        ->setLabel(pht('JIRA Issues'))
 115        ->setCaption(
 116          pht('Example: %s', phutil_tag('tt', array(), 'JIS-3, JIS-9')))
 117        ->setName($this->getFieldKey())
 118        ->setValue(implode(', ', nonempty($this->getValue(), array())))
 119        ->setError($this->error);
 120    }
 121  
 122    public function getOldValueForApplicationTransactions() {
 123      return array_unique(nonempty($this->getValue(), array()));
 124    }
 125  
 126    public function getNewValueForApplicationTransactions() {
 127      return array_unique(nonempty($this->getValue(), array()));
 128    }
 129  
 130    public function validateApplicationTransactions(
 131      PhabricatorApplicationTransactionEditor $editor,
 132      $type,
 133      array $xactions) {
 134  
 135      $this->error = null;
 136  
 137      $errors = parent::validateApplicationTransactions(
 138        $editor,
 139        $type,
 140        $xactions);
 141  
 142      $transaction = null;
 143      foreach ($xactions as $xaction) {
 144        $old = $xaction->getOldValue();
 145        $new = $xaction->getNewValue();
 146  
 147        $add = array_diff($new, $old);
 148        if (!$add) {
 149          continue;
 150        }
 151  
 152        // Only check that the actor can see newly added JIRA refs. You're
 153        // allowed to remove refs or make no-op changes even if you aren't
 154        // linked to JIRA.
 155  
 156        try {
 157          $refs = id(new DoorkeeperImportEngine())
 158            ->setViewer($this->getViewer())
 159            ->setRefs($this->buildDoorkeeperRefs($add))
 160            ->setThrowOnMissingLink(true)
 161            ->execute();
 162        } catch (DoorkeeperMissingLinkException $ex) {
 163          $this->error = pht('Not Linked');
 164          $errors[] = new PhabricatorApplicationTransactionValidationError(
 165            $type,
 166            pht('Not Linked'),
 167            pht(
 168              'You can not add JIRA issues (%s) to this revision because your '.
 169              'Phabricator account is not linked to a JIRA account.',
 170              implode(', ', $add)),
 171            $xaction);
 172          continue;
 173        }
 174  
 175        $bad = array();
 176        foreach ($refs as $ref) {
 177          if (!$ref->getIsVisible()) {
 178            $bad[] = $ref->getObjectID();
 179          }
 180        }
 181  
 182        if ($bad) {
 183          $bad = implode(', ', $bad);
 184          $this->error = pht('Invalid');
 185  
 186          $errors[] = new PhabricatorApplicationTransactionValidationError(
 187            $type,
 188            pht('Invalid'),
 189            pht(
 190              'Some JIRA issues could not be loaded. They may not exist, or '.
 191              'you may not have permission to view them: %s',
 192              $bad),
 193            $xaction);
 194        }
 195      }
 196  
 197      return $errors;
 198    }
 199  
 200    public function getApplicationTransactionTitle(
 201      PhabricatorApplicationTransaction $xaction) {
 202  
 203      $old = $xaction->getOldValue();
 204      if (!is_array($old)) {
 205        $old = array();
 206      }
 207  
 208      $new = $xaction->getNewValue();
 209      if (!is_array($new)) {
 210        $new = array();
 211      }
 212  
 213      $add = array_diff($new, $old);
 214      $rem = array_diff($old, $new);
 215  
 216      $author_phid = $xaction->getAuthorPHID();
 217      if ($add && $rem) {
 218        return pht(
 219          '%s updated JIRA issue(s): added %d %s; removed %d %s.',
 220          $xaction->renderHandleLink($author_phid),
 221          new PhutilNumber(count($add)),
 222          implode(', ', $add),
 223          new PhutilNumber(count($rem)),
 224          implode(', ', $rem));
 225      } else if ($add) {
 226        return pht(
 227          '%s added %d JIRA issue(s): %s.',
 228          $xaction->renderHandleLink($author_phid),
 229          new PhutilNumber(count($add)),
 230          implode(', ', $add));
 231      } else if ($rem) {
 232        return pht(
 233          '%s removed %d JIRA issue(s): %s.',
 234          $xaction->renderHandleLink($author_phid),
 235          new PhutilNumber(count($rem)),
 236          implode(', ', $rem));
 237      }
 238  
 239      return parent::getApplicationTransactionTitle($xaction);
 240    }
 241  
 242    public function applyApplicationTransactionExternalEffects(
 243      PhabricatorApplicationTransaction $xaction) {
 244  
 245      // Update the CustomField storage.
 246      parent::applyApplicationTransactionExternalEffects($xaction);
 247  
 248      // Now, synchronize the Doorkeeper edges.
 249      $revision = $this->getObject();
 250      $revision_phid = $revision->getPHID();
 251  
 252      $edge_type = PhabricatorEdgeConfig::TYPE_PHOB_HAS_JIRAISSUE;
 253      $xobjs = $this->loadDoorkeeperExternalObjects($xaction->getNewValue());
 254      $edge_dsts = mpull($xobjs, 'getPHID');
 255  
 256      $edges = PhabricatorEdgeQuery::loadDestinationPHIDs(
 257        $revision_phid,
 258        $edge_type);
 259  
 260      $editor = new PhabricatorEdgeEditor();
 261  
 262      foreach (array_diff($edges, $edge_dsts) as $rem_edge) {
 263        $editor->removeEdge($revision_phid, $edge_type, $rem_edge);
 264      }
 265  
 266      foreach (array_diff($edge_dsts, $edges) as $add_edge) {
 267        $editor->addEdge($revision_phid, $edge_type, $add_edge);
 268      }
 269  
 270      $editor->save();
 271    }
 272  
 273    public function shouldAppearInCommitMessage() {
 274      return true;
 275    }
 276  
 277    public function shouldAppearInCommitMessageTemplate() {
 278      return true;
 279    }
 280  
 281    public function getCommitMessageLabels() {
 282      return array(
 283        'JIRA',
 284        'JIRA Issues',
 285        'JIRA Issue',
 286      );
 287    }
 288  
 289    public function parseValueFromCommitMessage($value) {
 290      return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY);
 291    }
 292  
 293    public function readValueFromCommitMessage($value) {
 294      $this->setValue($value);
 295      return $this;
 296    }
 297  
 298  
 299  
 300    public function renderCommitMessageValue(array $handles) {
 301      $value = $this->getValue();
 302      if (!$value) {
 303        return null;
 304      }
 305      return implode(', ', $value);
 306    }
 307  
 308    public function shouldAppearInConduitDictionary() {
 309      return true;
 310    }
 311  
 312  
 313  }


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