[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/doorkeeper/worker/ -> DoorkeeperFeedWorkerJIRA.php (source)

   1  <?php
   2  
   3  /**
   4   * Publishes feed stories into JIRA, using the "JIRA Issues" field to identify
   5   * linked issues.
   6   */
   7  final class DoorkeeperFeedWorkerJIRA extends DoorkeeperFeedWorker {
   8  
   9    private $provider;
  10  
  11  
  12  /* -(  Publishing Stories  )------------------------------------------------- */
  13  
  14  
  15    /**
  16     * This worker is enabled when a JIRA authentication provider is active.
  17     */
  18    public function isEnabled() {
  19      return (bool)PhabricatorJIRAAuthProvider::getJIRAProvider();
  20    }
  21  
  22  
  23    /**
  24     * Publishes stories into JIRA using the JIRA API.
  25     */
  26    protected function publishFeedStory() {
  27      $story = $this->getFeedStory();
  28      $viewer = $this->getViewer();
  29      $provider = $this->getProvider();
  30      $object = $this->getStoryObject();
  31      $publisher = $this->getPublisher();
  32  
  33      $jira_issue_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
  34        $object->getPHID(),
  35        PhabricatorEdgeConfig::TYPE_PHOB_HAS_JIRAISSUE);
  36      if (!$jira_issue_phids) {
  37        $this->log("Story is about an object with no linked JIRA issues.\n");
  38        return;
  39      }
  40  
  41      $xobjs = id(new DoorkeeperExternalObjectQuery())
  42        ->setViewer($viewer)
  43        ->withPHIDs($jira_issue_phids)
  44        ->execute();
  45  
  46      if (!$xobjs) {
  47        $this->log("Story object has no corresponding external JIRA objects.\n");
  48        return;
  49      }
  50  
  51      $try_users = $this->findUsersToPossess();
  52      if (!$try_users) {
  53        $this->log("No users to act on linked JIRA objects.\n");
  54        return;
  55      }
  56  
  57      $story_text = $this->renderStoryText();
  58  
  59      $xobjs = mgroup($xobjs, 'getApplicationDomain');
  60      foreach ($xobjs as $domain => $xobj_list) {
  61        $accounts = id(new PhabricatorExternalAccountQuery())
  62          ->setViewer($viewer)
  63          ->withUserPHIDs($try_users)
  64          ->withAccountTypes(array($provider->getProviderType()))
  65          ->withAccountDomains(array($domain))
  66          ->requireCapabilities(
  67            array(
  68              PhabricatorPolicyCapability::CAN_VIEW,
  69              PhabricatorPolicyCapability::CAN_EDIT,
  70            ))
  71          ->execute();
  72        // Reorder accounts in the original order.
  73        // TODO: This needs to be adjusted if/when we allow you to link multiple
  74        // accounts.
  75        $accounts = mpull($accounts, null, 'getUserPHID');
  76        $accounts = array_select_keys($accounts, $try_users);
  77  
  78        foreach ($xobj_list as $xobj) {
  79          foreach ($accounts as $account) {
  80            try {
  81              $provider->newJIRAFuture(
  82                $account,
  83                'rest/api/2/issue/'.$xobj->getObjectID().'/comment',
  84                'POST',
  85                array(
  86                  'body' => $story_text,
  87                ))->resolveJSON();
  88              break;
  89            } catch (HTTPFutureResponseStatus $ex) {
  90              phlog($ex);
  91              $this->log(
  92                "Failed to update object %s using user %s.\n",
  93                $xobj->getObjectID(),
  94                $account->getUserPHID());
  95            }
  96          }
  97        }
  98      }
  99    }
 100  
 101  
 102  /* -(  Internals  )---------------------------------------------------------- */
 103  
 104  
 105    /**
 106     * Get the active JIRA provider.
 107     *
 108     * @return PhabricatorJIRAAuthProvider Active JIRA auth provider.
 109     * @task internal
 110     */
 111    private function getProvider() {
 112      if (!$this->provider) {
 113        $provider = PhabricatorJIRAAuthProvider::getJIRAProvider();
 114        if (!$provider) {
 115          throw new PhabricatorWorkerPermanentFailureException(
 116            'No JIRA provider configured.');
 117        }
 118        $this->provider = $provider;
 119      }
 120      return $this->provider;
 121    }
 122  
 123  
 124    /**
 125     * Get a list of users to act as when publishing into JIRA.
 126     *
 127     * @return list<phid> Candidate user PHIDs to act as when publishing this
 128     *                    story.
 129     * @task internal
 130     */
 131    private function findUsersToPossess() {
 132      $object = $this->getStoryObject();
 133      $publisher = $this->getPublisher();
 134      $data = $this->getFeedStory()->getStoryData();
 135  
 136      // Figure out all the users related to the object. Users go into one of
 137      // four buckets. For JIRA integration, we don't care about which bucket
 138      // a user is in, since we just want to publish an update to linked objects.
 139  
 140      $owner_phid = $publisher->getOwnerPHID($object);
 141      $active_phids = $publisher->getActiveUserPHIDs($object);
 142      $passive_phids = $publisher->getPassiveUserPHIDs($object);
 143      $follow_phids = $publisher->getCCUserPHIDs($object);
 144  
 145      $all_phids = array_merge(
 146        array($owner_phid),
 147        $active_phids,
 148        $passive_phids,
 149        $follow_phids);
 150      $all_phids = array_unique(array_filter($all_phids));
 151  
 152      // Even if the actor isn't a reviewer, etc., try to use their account so
 153      // we can post in the correct voice. If we miss, we'll try all the other
 154      // related users.
 155  
 156      $try_users = array_merge(
 157        array($data->getAuthorPHID()),
 158        $all_phids);
 159      $try_users = array_filter($try_users);
 160  
 161      return $try_users;
 162    }
 163  
 164    private function renderStoryText() {
 165      $object = $this->getStoryObject();
 166      $publisher = $this->getPublisher();
 167  
 168      $text = $publisher->getStoryText($object);
 169      $uri = $publisher->getObjectURI($object);
 170  
 171      return $text."\n\n".$uri;
 172    }
 173  
 174  }


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