Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/doorkeeper/bridge/DoorkeeperBridgeGitHubUser.php
12256 views
1
<?php
2
3
final class DoorkeeperBridgeGitHubUser
4
extends DoorkeeperBridgeGitHub {
5
6
const OBJTYPE_GITHUB_USER = 'github.user';
7
8
public function canPullRef(DoorkeeperObjectRef $ref) {
9
if (!parent::canPullRef($ref)) {
10
return false;
11
}
12
13
if ($ref->getObjectType() !== self::OBJTYPE_GITHUB_USER) {
14
return false;
15
}
16
17
return true;
18
}
19
20
public function pullRefs(array $refs) {
21
$token = $this->getGitHubAccessToken();
22
if (!strlen($token)) {
23
return null;
24
}
25
26
$template = id(new PhutilGitHubFuture())
27
->setAccessToken($token);
28
29
$futures = array();
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";
37
38
$data = array();
39
$futures[$key] = id(clone $template)
40
->setRawGitHubQuery($uri, $data);
41
}
42
43
$results = array();
44
$failed = array();
45
foreach (new FutureIterator($futures) as $key => $future) {
46
try {
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
52
// objects?
53
} else {
54
phlog($ex);
55
$failed[$key] = $ex;
56
}
57
}
58
}
59
60
$viewer = $this->getViewer();
61
62
foreach ($refs as $ref) {
63
$ref->setAttribute('name', pht('GitHub User %s', $ref->getObjectID()));
64
65
$did_fail = idx($failed, $ref->getObjectKey());
66
if ($did_fail) {
67
$ref->setSyncFailed(true);
68
continue;
69
}
70
71
$result = idx($results, $ref->getObjectKey());
72
if (!$result) {
73
continue;
74
}
75
76
$body = $result->getBody();
77
if (!is_array($body) || !count($body)) {
78
$ref->setSyncFailed(true);
79
continue;
80
}
81
82
$spec = head($body);
83
if (!is_array($spec)) {
84
$ref->setSyncFailed(true);
85
continue;
86
}
87
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);
95
continue;
96
}
97
98
$ref->setIsVisible(true);
99
$ref->setAttribute('api.raw', $spec);
100
$ref->setAttribute('name', $spec['login']);
101
102
$obj = $ref->getExternalObject();
103
$this->fillObjectFromData($obj, $spec);
104
$this->saveExternalObject($ref, $obj);
105
}
106
}
107
108
public function fillObjectFromData(DoorkeeperExternalObject $obj, $spec) {
109
$uri = $spec['html_url'];
110
$obj->setObjectURI($uri);
111
112
$login = $spec['login'];
113
114
$obj->setDisplayName(pht('%s <%s>', $login, pht('GitHub')));
115
}
116
117
}
118
119