3 final class DoorkeeperBridgeGitHubUser
4 extends DoorkeeperBridgeGitHub
{
6 const OBJTYPE_GITHUB_USER
= 'github.user';
8 public function canPullRef(DoorkeeperObjectRef
$ref) {
9 if (!parent
::canPullRef($ref)) {
13 if ($ref->getObjectType() !== self
::OBJTYPE_GITHUB_USER
) {
20 public function pullRefs(array $refs) {
21 $token = $this->getGitHubAccessToken();
22 if (!strlen($token)) {
26 $template = id(new PhutilGitHubFuture())
27 ->setAccessToken($token);
30 $id_map = mpull($refs, 'getObjectID', 'getObjectKey');
31 foreach ($id_map as $key => $id) {
32 // GitHub doesn't provide a way to query for users by ID directly, but we
33 // can list all users, ordered by ID, starting at some particular ID,
34 // with a page size of one, which will achieve the desired effect.
35 $one_less = ($id - 1);
36 $uri = "/users?since={$one_less}&per_page=1";
39 $futures[$key] = id(clone $template)
40 ->setRawGitHubQuery($uri, $data);
45 foreach (new FutureIterator($futures) as $key => $future) {
47 $results[$key] = $future->resolve();
48 } catch (Exception
$ex) {
49 if (($ex instanceof HTTPFutureResponseStatus
) &&
50 ($ex->getStatusCode() == 404)) {
51 // TODO: Do we end up here for deleted objects and invisible
60 $viewer = $this->getViewer();
62 foreach ($refs as $ref) {
63 $ref->setAttribute('name', pht('GitHub User %s', $ref->getObjectID()));
65 $did_fail = idx($failed, $ref->getObjectKey());
67 $ref->setSyncFailed(true);
71 $result = idx($results, $ref->getObjectKey());
76 $body = $result->getBody();
77 if (!is_array($body) ||
!count($body)) {
78 $ref->setSyncFailed(true);
83 if (!is_array($spec)) {
84 $ref->setSyncFailed(true);
88 // Because we're using a paging query to load each user, if a user (say,
89 // user ID 123) does not exist for some reason, we might get the next
90 // user (say, user ID 124) back. Make sure the user we got back is really
91 // the user we expect.
92 $id = idx($spec, 'id');
93 if ($id !== $ref->getObjectID()) {
94 $ref->setSyncFailed(true);
98 $ref->setIsVisible(true);
99 $ref->setAttribute('api.raw', $spec);
100 $ref->setAttribute('name', $spec['login']);
102 $obj = $ref->getExternalObject();
103 $this->fillObjectFromData($obj, $spec);
104 $this->saveExternalObject($ref, $obj);
108 public function fillObjectFromData(DoorkeeperExternalObject
$obj, $spec) {
109 $uri = $spec['html_url'];
110 $obj->setObjectURI($uri);
112 $login = $spec['login'];
114 $obj->setDisplayName(pht('%s <%s>', $login, pht('GitHub')));