[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/doorkeeper/bridge/ -> DoorkeeperBridgeJIRA.php (source)

   1  <?php
   2  
   3  final class DoorkeeperBridgeJIRA extends DoorkeeperBridge {
   4  
   5    const APPTYPE_JIRA = 'jira';
   6    const OBJTYPE_ISSUE = 'jira:issue';
   7  
   8    public function canPullRef(DoorkeeperObjectRef $ref) {
   9      if ($ref->getApplicationType() != self::APPTYPE_JIRA) {
  10        return false;
  11      }
  12  
  13      $types = array(
  14        self::OBJTYPE_ISSUE => true,
  15      );
  16  
  17      return isset($types[$ref->getObjectType()]);
  18    }
  19  
  20    public function pullRefs(array $refs) {
  21  
  22      $id_map = mpull($refs, 'getObjectID', 'getObjectKey');
  23      $viewer = $this->getViewer();
  24  
  25      $provider = PhabricatorJIRAAuthProvider::getJIRAProvider();
  26      if (!$provider) {
  27        return;
  28      }
  29  
  30      $accounts = id(new PhabricatorExternalAccountQuery())
  31        ->setViewer($viewer)
  32        ->withUserPHIDs(array($viewer->getPHID()))
  33        ->withAccountTypes(array($provider->getProviderType()))
  34        ->requireCapabilities(
  35          array(
  36            PhabricatorPolicyCapability::CAN_VIEW,
  37            PhabricatorPolicyCapability::CAN_EDIT,
  38          ))
  39        ->execute();
  40  
  41      if (!$accounts) {
  42        return $this->didFailOnMissingLink();
  43      }
  44  
  45      // TODO: When we support multiple JIRA instances, we need to disambiguate
  46      // issues (perhaps with additional configuration) or cast a wide net
  47      // (by querying all instances). For now, just query the one instance.
  48      $account = head($accounts);
  49  
  50      $futures = array();
  51      foreach ($id_map as $key => $id) {
  52        $futures[$key] = $provider->newJIRAFuture(
  53          $account,
  54          'rest/api/2/issue/'.phutil_escape_uri($id),
  55          'GET');
  56      }
  57  
  58      $results = array();
  59      $failed = array();
  60      foreach (Futures($futures) as $key => $future) {
  61        try {
  62          $results[$key] = $future->resolveJSON();
  63        } catch (Exception $ex) {
  64          if (($ex instanceof HTTPFutureResponseStatus) &&
  65              ($ex->getStatusCode() == 404)) {
  66            // This indicates that the object has been deleted (or never existed,
  67            // or isn't visible to the current user) but it's a successful sync of
  68            // an object which isn't visible.
  69          } else {
  70            // This is something else, so consider it a synchronization failure.
  71            phlog($ex);
  72            $failed[$key] = $ex;
  73          }
  74        }
  75      }
  76  
  77      foreach ($refs as $ref) {
  78        $ref->setAttribute('name', pht('JIRA %s', $ref->getObjectID()));
  79  
  80        $did_fail = idx($failed, $ref->getObjectKey());
  81        if ($did_fail) {
  82          $ref->setSyncFailed(true);
  83          continue;
  84        }
  85  
  86        $result = idx($results, $ref->getObjectKey());
  87        if (!$result) {
  88          continue;
  89        }
  90  
  91        $fields = idx($result, 'fields', array());
  92  
  93        $ref->setIsVisible(true);
  94        $ref->setAttribute(
  95          'fullname',
  96          pht('JIRA %s %s', $result['key'], idx($fields, 'summary')));
  97  
  98        $ref->setAttribute('title', idx($fields, 'summary'));
  99        $ref->setAttribute('description', idx($result, 'description'));
 100  
 101        $obj = $ref->getExternalObject();
 102        if ($obj->getID()) {
 103          continue;
 104        }
 105  
 106        $this->fillObjectFromData($obj, $result);
 107  
 108        $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 109          $obj->save();
 110        unset($unguarded);
 111      }
 112    }
 113  
 114    public function fillObjectFromData(DoorkeeperExternalObject $obj, $result) {
 115      // Convert the "self" URI, which points at the REST endpoint, into a
 116      // browse URI.
 117      $self = idx($result, 'self');
 118      $object_id = $obj->getObjectID();
 119  
 120      $uri = self::getJIRAIssueBrowseURIFromJIRARestURI($self, $object_id);
 121      if ($uri !== null) {
 122        $obj->setObjectURI($uri);
 123      }
 124    }
 125  
 126    public static function getJIRAIssueBrowseURIFromJIRARestURI(
 127      $uri,
 128      $object_id) {
 129  
 130      $uri = new PhutilURI($uri);
 131  
 132      // The JIRA install might not be at the domain root, so we may need to
 133      // keep an initial part of the path, like "/jira/". Find the API specific
 134      // part of the URI, strip it off, then replace it with the web version.
 135      $path = $uri->getPath();
 136      $pos = strrpos($path, 'rest/api/2/issue/');
 137      if ($pos === false) {
 138        return null;
 139      }
 140  
 141      $path = substr($path, 0, $pos);
 142      $path = $path.'browse/'.$object_id;
 143      $uri->setPath($path);
 144  
 145      return (string)$uri;
 146    }
 147  
 148  }


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