This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Hubph; |
||
4 | |||
5 | use Consolidation\Config\ConfigInterface; |
||
6 | use Hubph\Internal\EventLogger; |
||
7 | |||
8 | class HubphAPI |
||
9 | { |
||
10 | protected $config; |
||
11 | protected $token; |
||
12 | protected $gitHubAPI; |
||
13 | protected $eventLogger; |
||
14 | protected $as = 'default'; |
||
15 | |||
16 | /** |
||
17 | * HubphAPI constructor |
||
18 | */ |
||
19 | public function __construct(ConfigInterface $config) |
||
20 | { |
||
21 | $this->config = $config; |
||
22 | } |
||
23 | |||
24 | public function startLogging($filename) |
||
25 | { |
||
26 | $this->stopLogging(); |
||
27 | $this->eventLogger = new EventLogger($filename); |
||
28 | $this->eventLogger->start(); |
||
29 | } |
||
30 | |||
31 | public function stopLogging() |
||
32 | { |
||
33 | if ($this->eventLogger) { |
||
34 | $this->eventLogger->stop(); |
||
35 | } |
||
36 | $this->eventLogger = null; |
||
37 | } |
||
38 | |||
39 | public function setAs($as) |
||
40 | { |
||
41 | if ($as != $this->as) { |
||
42 | $this->as = $as; |
||
43 | $this->token = false; |
||
44 | $this->gitHubAPI = false; |
||
45 | } |
||
46 | } |
||
47 | |||
48 | public function whoami() |
||
49 | { |
||
50 | $gitHubAPI = $this->gitHubAPI(); |
||
51 | $authenticated = $gitHubAPI->api('current_user')->show(); |
||
52 | return $authenticated; |
||
53 | } |
||
54 | |||
55 | public function repoCreate($org, $project) |
||
56 | { |
||
57 | return $this->api->gitHubAPI()->api('repo')->create( |
||
58 | $project, |
||
59 | '', |
||
60 | '', |
||
61 | true, |
||
62 | $org |
||
63 | ); |
||
64 | } |
||
65 | |||
66 | public function repoDelete($org, $project) |
||
67 | { |
||
68 | return $this->api->gitHubAPI()->api('repo')->remove($org, $project); |
||
69 | } |
||
70 | |||
71 | public function prCreate($org, $project, $title, $body, $base, $head) |
||
72 | { |
||
73 | $params = [ |
||
74 | 'title' => $title, |
||
75 | 'body' => $body, |
||
76 | 'base' => $base, |
||
77 | 'head' => $head, |
||
78 | ]; |
||
79 | $response = $this->gitHubAPI()->api('pull_request')->create($org, $project, $params); |
||
80 | $this->logEvent(__FUNCTION__, [$org, $project], $params, $response); |
||
81 | return $this; |
||
82 | } |
||
83 | |||
84 | public function prClose($org, $project, PullRequests $prs) |
||
85 | { |
||
86 | foreach ($prs->prNumbers() as $n) { |
||
87 | $gitHubAPI = $this->gitHubAPI(); |
||
88 | $gitHubAPI->api('pull_request')->update($org, $project, $n, ['state' => 'closed']); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | public function prMerge($org, $project, PullRequests $prs, $message, $mergeMethod = 'squash', $title = null) |
||
93 | { |
||
94 | // First, check to see if all of the pull requests can be merged, |
||
95 | // and collect the sha hash of the head of the branch. |
||
96 | $allClean = true; |
||
97 | $shas = []; |
||
98 | foreach ($prs->prNumbers() as $n) { |
||
99 | $pullRequest = $this->gitHubAPI()->api('pull_request')->show($org, $project, $n); |
||
100 | $is_clean = $pullRequest['mergeable'] && $pullRequest['mergeable_state'] == 'clean'; |
||
101 | if (!$is_clean) { |
||
102 | return false; |
||
103 | } |
||
104 | $shas[$n] = $pullRequest['head']['sha']; |
||
105 | } |
||
106 | |||
107 | // Merge all of the pull requests |
||
108 | foreach ($shas as $n => $sha) { |
||
109 | $response = $this->gitHubAPI()->api('pull_request')->merge($org, $project, $n, $message, $sha, $mergeMethod, $title); |
||
110 | $this->logEvent(__FUNCTION__, [$org, $project], [$n, $message, $sha, $mergeMethod, $title], $response); |
||
111 | } |
||
112 | return true; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * prCheck determines whether there are any open PRs that already exist |
||
117 | * that satisfy any of the provided $vids. |
||
118 | * |
||
119 | * @param string $projectWithOrg org/project to check |
||
120 | * @param VersionIdentifiers $vids |
||
121 | * @return [int $status, PullRequests $prs] status of PRs, and a list of PR numbers |
||
122 | * - If $status is 0, then the caller should go ahead and create a new PR. |
||
123 | * The existing pull requests that would be superceded by the new PR are |
||
124 | * returned in the second parameter. These PRs could all be closed. |
||
125 | * - If $status is >0, then there is no need to create a new PR, as there |
||
126 | * are already existing PRs that are equivalent to the one that would |
||
127 | * be open. The equivalent PRs are returned in the second parameter. |
||
128 | */ |
||
129 | public function prCheck($projectWithOrg, VersionIdentifiers $vids) |
||
130 | { |
||
131 | // Find all of the PRs that contain any vid |
||
132 | $existingPRs = $this->existingPRs($projectWithOrg, $vids); |
||
133 | |||
134 | // Check to see if there are PRs matching all of the vids/vvals. |
||
135 | $titles = $existingPRs->titles(); |
||
136 | $status = $vids->allExist($titles); |
||
137 | |||
138 | return [$status, $existingPRs]; |
||
139 | } |
||
140 | |||
141 | public function prStatuses($projectWithOrg, $number) |
||
142 | { |
||
143 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
144 | $pullRequestStatus = $this->gitHubAPI()->api('pull_request')->status($org, $project, $number); |
||
145 | |||
146 | // Filter out the results based on 'target_url' |
||
147 | $filteredResults = []; |
||
148 | foreach (array_reverse($pullRequestStatus) as $id => $item) { |
||
149 | $filteredResults[$item['target_url']] = $item; |
||
150 | } |
||
151 | $pullRequestStatus = []; |
||
152 | foreach ($filteredResults as $target_url => $item) { |
||
153 | $pullRequestStatus[$item['id']] = $item; |
||
154 | } |
||
155 | |||
156 | // Put the most recently updated statuses at the top of the list |
||
157 | uasort( |
||
158 | |||
159 | $pullRequestStatus, |
||
160 | function ($lhs, $rhs) { |
||
161 | return abs(strtotime($lhs['updated_at']) - strtotime($rhs['updated_at'])); |
||
162 | } |
||
163 | ); |
||
164 | |||
165 | return $pullRequestStatus; |
||
166 | } |
||
167 | |||
168 | public function addTokenAuthentication($url) |
||
169 | { |
||
170 | $token = $this->gitHubToken(); |
||
171 | if (!$token) { |
||
172 | return $url; |
||
173 | } |
||
174 | if (!preg_match('#github\.com[/:]#', $url)) { |
||
175 | return $url; |
||
176 | } |
||
177 | $projectAndOrg = $this->projectAndOrgFromUrl($url); |
||
178 | return "https://{$token}:[email protected]/{$projectAndOrg}.git"; |
||
179 | } |
||
180 | |||
181 | View Code Duplication | protected function projectAndOrgFromUrl($remote) |
|
0 ignored issues
–
show
|
|||
182 | { |
||
183 | $remote = preg_replace('#^git@[^:]*:#', '', $remote); |
||
184 | $remote = preg_replace('#^[^:]*://[^/]*/#', '', $remote); |
||
185 | $remote = preg_replace('#\.git$#', '', $remote); |
||
186 | |||
187 | return $remote; |
||
188 | } |
||
189 | |||
190 | protected function existingPRs($projectWithOrg, VersionIdentifiers $vids) |
||
191 | { |
||
192 | return $this->matchingPRs($projectWithOrg, $vids->getPreamble(), $vids->pattern()); |
||
193 | } |
||
194 | |||
195 | public function matchingPRs($projectWithOrg, $preamble, $pattern = '') |
||
196 | { |
||
197 | $q = "repo:$projectWithOrg in:title is:pr state:open $preamble"; |
||
198 | $result = new PullRequests(); |
||
199 | $gitHubAPI = $this->gitHubAPI(); |
||
200 | $searchResults = $gitHubAPI->api('search')->issues($q); |
||
201 | $result->addSearchResults($searchResults, $pattern); |
||
202 | |||
203 | return $result; |
||
204 | } |
||
205 | |||
206 | public function allPRs($projectWithOrg) |
||
207 | { |
||
208 | $q = "repo:$projectWithOrg in:title is:pr state:open"; |
||
209 | $result = new PullRequests(); |
||
210 | $searchResults = $this->gitHubAPI()->api('search')->issues($q); |
||
211 | $result->addSearchResults($searchResults); |
||
212 | |||
213 | return $result; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Pass an event of note to the event logger |
||
218 | * @param string $event_name |
||
219 | * @param array $args |
||
220 | * @param array $params |
||
221 | * @param array $response |
||
222 | */ |
||
223 | protected function logEvent($event_name, $args, $params, $response) |
||
224 | { |
||
225 | if ($this->eventLogger) { |
||
226 | $this->eventLogger->log($event_name, $args, $params, $response); |
||
227 | } |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Authenticate and then return the gitHub API object. |
||
232 | */ |
||
233 | public function gitHubAPI() |
||
234 | { |
||
235 | if (!$this->gitHubAPI) { |
||
236 | $token = $this->gitHubToken(); |
||
237 | |||
238 | $this->gitHubAPI = new \Github\Client(); |
||
239 | $this->gitHubAPI->authenticate($token, null, \Github\Client::AUTH_HTTP_TOKEN); |
||
240 | } |
||
241 | return $this->gitHubAPI; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Return a result pager object using our cached GitHub API client. |
||
246 | */ |
||
247 | public function resultPager() |
||
248 | { |
||
249 | return new \Github\ResultPager($this->gitHubAPI()); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Look up the GitHub token set either via environment variable or in the |
||
254 | * auth-token cache directory. |
||
255 | */ |
||
256 | public function gitHubToken() |
||
257 | { |
||
258 | if (!$this->token) { |
||
259 | $this->token = $this->getGitHubToken(); |
||
260 | } |
||
261 | return $this->token; |
||
262 | } |
||
263 | |||
264 | protected function getGitHubToken() |
||
265 | { |
||
266 | $as = $this->as; |
||
267 | $token = null; |
||
268 | if ($as == 'default') { |
||
269 | $as = $this->getConfig()->get("github.default-user"); |
||
270 | } |
||
271 | |||
272 | // First preference: There is a 'path' component in preferences |
||
273 | // pointing to a file containing the token. |
||
274 | $github_token_cache = $this->getConfig()->get("github.personal-auth-token.$as.path"); |
||
275 | if (file_exists($github_token_cache)) { |
||
276 | $token = trim(file_get_contents($github_token_cache)); |
||
277 | } |
||
278 | |||
279 | // Second preference: There is an environment variable that begins |
||
280 | // with an uppercased version of the 'as' string followed by '_TOKEN' |
||
281 | if (!$token) { |
||
282 | $env_name = strtoupper(str_replace('-', '_', $as)) . '_TOKEN'; |
||
283 | $token = getenv($env_name); |
||
284 | } |
||
285 | |||
286 | // If we read in a token from one of the preferred locations, then |
||
287 | // set the GITHUB_TOKEN environment variable and return it. |
||
288 | if ($token) { |
||
289 | putenv("GITHUB_TOKEN=$token"); |
||
290 | return $token; |
||
291 | } |
||
292 | |||
293 | // Fallback: authenticate to whatever 'GITHUB_TOKEN' is already set to. |
||
294 | return getenv('GITHUB_TOKEN'); |
||
295 | } |
||
296 | |||
297 | protected function getConfig() |
||
298 | { |
||
299 | return $this->config; |
||
300 | } |
||
301 | } |
||
302 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.