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\Cli; |
||
4 | |||
5 | use Consolidation\AnnotatedCommand\CommandData; |
||
6 | use Consolidation\Filter\FilterOutputData; |
||
7 | use Consolidation\Filter\LogicalOpFactory; |
||
8 | use Consolidation\OutputFormatters\Options\FormatterOptions; |
||
9 | use Consolidation\OutputFormatters\StructuredData\RowsOfFields; |
||
10 | use Consolidation\OutputFormatters\StructuredData\PropertyList; |
||
11 | use Psr\Log\LoggerAwareInterface; |
||
12 | use Psr\Log\LoggerAwareTrait; |
||
13 | use Robo\Common\ConfigAwareTrait; |
||
14 | use Robo\Contract\ConfigAwareInterface; |
||
15 | use Consolidation\AnnotatedCommand\CommandError; |
||
16 | use Hubph\HubphAPI; |
||
17 | use Hubph\VersionIdentifiers; |
||
18 | use Hubph\PullRequests; |
||
19 | use Hubph\Git\WorkingCopy; |
||
20 | |||
21 | class HubphCommands extends \Robo\Tasks implements ConfigAwareInterface, LoggerAwareInterface |
||
22 | { |
||
23 | use ConfigAwareTrait; |
||
24 | use LoggerAwareTrait; |
||
25 | |||
26 | /** |
||
27 | * Report who we have authenticated as |
||
28 | * |
||
29 | * @command whoami |
||
30 | */ |
||
31 | public function whoami($options = ['as' => 'default']) |
||
32 | { |
||
33 | $api = $this->api($options['as']); |
||
34 | $authenticated = $api->whoami(); |
||
35 | $authenticatedUser = $authenticated['login']; |
||
36 | |||
37 | $this->say("Authenticated as $authenticatedUser."); |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * @command pr:close |
||
42 | */ |
||
43 | View Code Duplication | public function prClose($projectWithOrg = '', $number = '', $options = ['as' => 'default']) |
|
0 ignored issues
–
show
|
|||
44 | { |
||
45 | if (empty($number) && preg_match('#^[0-9]*$#', $projectWithOrg)) { |
||
46 | $number = $projectWithOrg; |
||
47 | $projectWithOrg = ''; |
||
48 | } |
||
49 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
50 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
51 | |||
52 | $api = $this->api($options['as']); |
||
53 | $api->prClose($org, $project, $number); |
||
0 ignored issues
–
show
$number is of type string , but the function expects a object<Hubph\PullRequests> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
54 | } |
||
55 | |||
56 | /* |
||
57 | * hubph pr:check --vid=php-7.0./31 --vid=php-7.1./20 |
||
58 | * |
||
59 | * status 0 and csv with PR numbers to close |
||
60 | * |
||
61 | * - or - |
||
62 | * |
||
63 | * status 1 if all vid/vvals exist and nothing more needs to be done |
||
64 | */ |
||
65 | |||
66 | /** |
||
67 | * @command pr:check |
||
68 | */ |
||
69 | public function prCheck( |
||
70 | $options = [ |
||
71 | 'message|m' => '', |
||
72 | 'file|F' => '', |
||
73 | 'base' => '', |
||
74 | 'head' => '', |
||
75 | 'as' => 'default', |
||
76 | 'format' => 'yaml', |
||
77 | 'idempotent' => false |
||
78 | ] |
||
79 | ) { |
||
80 | $projectWithOrg = $this->projectWithOrg(); |
||
81 | |||
82 | // Get the commit message from --message or --file |
||
83 | $message = $this->getMessage($options); |
||
84 | |||
85 | // Determine all of the vid/vval pairs if idempotent |
||
86 | $vids = $this->getVids($options, $message); |
||
87 | |||
88 | $api = $this->api($options['as']); |
||
89 | list($status, $result) = $api->prCheck($projectWithOrg, $vids); |
||
90 | |||
91 | if ($status) { |
||
92 | return new CommandError($result, $status); |
||
0 ignored issues
–
show
$status is of type boolean , but the function expects a integer .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
93 | } |
||
94 | if (is_string($result)) { |
||
95 | $this->logger->notice("No open pull requests that need to be closed."); |
||
96 | return; |
||
97 | } |
||
98 | return implode(',', (array)$result); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * @command pr:create |
||
103 | * @aliases pull-request |
||
104 | */ |
||
105 | public function prCreate( |
||
106 | $options = [ |
||
107 | 'message|m' => '', |
||
108 | 'body' => '', |
||
109 | 'file|F' => '', |
||
110 | 'base' => 'master', |
||
111 | 'head' => '', |
||
112 | 'as' => 'default', |
||
113 | 'format' => 'yaml', |
||
114 | 'idempotent' => false |
||
115 | ] |
||
116 | ) { |
||
117 | $projectWithOrg = $this->projectWithOrg(); |
||
118 | |||
119 | // Get the commit message from --message or --file |
||
120 | $message = $this->getMessage($options); |
||
121 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
122 | |||
123 | // Determine all of the vid/vval pairs if idempotent |
||
124 | $vids = $this->getVids($options, $message); |
||
125 | |||
126 | $api = $this->api($options['as']); |
||
127 | list($status, $result) = $api->prCheck($projectWithOrg, $vids); |
||
128 | |||
129 | if ($status) { |
||
130 | return new CommandError($result, $status); |
||
0 ignored issues
–
show
$status is of type boolean , but the function expects a integer .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
131 | } |
||
132 | |||
133 | // TODO: We could look up 'head' if it is not provided. |
||
134 | if (empty($options['head'])) { |
||
135 | throw new \Exceptions('Must provide --head'); |
||
136 | } |
||
137 | |||
138 | // Create the requested PR |
||
139 | $api->prCreate($org, $project, $message, $options['body'], $options['base'], $options['head']); |
||
140 | |||
141 | // If $result is an array, it will contain |
||
142 | // all of the pull request numbers to close. |
||
143 | // TODO: We should make a wrapper object for $result |
||
144 | if (is_array($result)) { |
||
145 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
146 | $api->prClose($org, $project, $result); |
||
0 ignored issues
–
show
$result is of type array , but the function expects a object<Hubph\PullRequests> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
147 | } |
||
148 | } |
||
149 | |||
150 | protected function getMessage($options) |
||
151 | { |
||
152 | if (!empty($options['message'])) { |
||
153 | return $options['message']; |
||
154 | } |
||
155 | if (!empty($options['file'])) { |
||
156 | return file_get_contents($options['file']); |
||
157 | } |
||
158 | return ''; |
||
159 | } |
||
160 | |||
161 | protected function getVids($options, $message) |
||
162 | { |
||
163 | $vids = new VersionIdentifiers(); |
||
164 | |||
165 | //if (empty($options['idempotent'])) { |
||
166 | // return $vids; |
||
167 | //} |
||
168 | |||
169 | // Allow the caller to define more specific vid / vval patterns |
||
170 | if (!empty($options['vid'])) { |
||
171 | $vids->setVidPattern($options['vid']); |
||
172 | } |
||
173 | if (!empty($options['vval'])) { |
||
174 | $vids->setVvalPattern($options['vval']); |
||
175 | } |
||
176 | |||
177 | $vids->addVidsFromMessage($message); |
||
178 | return $vids; |
||
179 | } |
||
180 | |||
181 | protected function projectWithOrg($projectWithOrg = '') |
||
182 | { |
||
183 | if (!empty($projectWithOrg)) { |
||
184 | return $projectWithOrg; |
||
185 | } |
||
186 | |||
187 | return $this->getProjectWithOrgFromRemote(); |
||
188 | } |
||
189 | |||
190 | protected function getProjectWithOrgFromRemote($remote = 'origin', $cwd = '') |
||
191 | { |
||
192 | $remote = $this->getRemote($remote, $cwd); |
||
193 | |||
194 | return $this->getProjectWithOrfFromUrl($remote); |
||
195 | } |
||
196 | |||
197 | View Code Duplication | protected function getProjectWithOrfFromUrl($remote) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
198 | { |
||
199 | $remote = preg_replace('#^git@[^:]*:#', '', $remote); |
||
200 | $remote = preg_replace('#^[^:]*://[^/]/#', '', $remote); |
||
201 | $remote = preg_replace('#\.git$#', '', $remote); |
||
202 | |||
203 | return $remote; |
||
204 | } |
||
205 | |||
206 | protected function getRemote($remote = 'origin', $cwd = '') |
||
207 | { |
||
208 | if (!empty($cwd)) { |
||
209 | $cwd = "-C $cwd"; |
||
210 | } |
||
211 | return exec("git {$cwd} config --get remote.{$remote}.url"); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * @command pr:find |
||
216 | * @param $projectWithOrg The project to work on, e.g. org/project |
||
217 | * @option $q Query term |
||
218 | * @filter-output |
||
219 | * @field-labels |
||
220 | * url: Url |
||
221 | * id: ID |
||
222 | * node_id: Node ID |
||
223 | * html_url: HTML Url |
||
224 | * diff_url: Diff Url |
||
225 | * patch_url: Patch Url |
||
226 | * issue_url: Issue Url |
||
227 | * number: Number |
||
228 | * state: State |
||
229 | * locked: Locked |
||
230 | * title: Title |
||
231 | * user: User |
||
232 | * body: Boday |
||
233 | * created_at: Created |
||
234 | * updated_at: Updated |
||
235 | * closed_at: Closed |
||
236 | * merged_at: Merged |
||
237 | * merge_commit_sha: Merge Commit |
||
238 | * assignee: Assignee |
||
239 | * assignees: Assignees |
||
240 | * requested_reviewers: Requested Reviewers |
||
241 | * requested_teams: Requested Teams |
||
242 | * labels: Labels |
||
243 | * milestone: Milestone |
||
244 | * commits_url: Commit Url |
||
245 | * review_comments_url: Review Comments Url |
||
246 | * review_comment_url: Review Comment Url |
||
247 | * comments_url: Comments Url |
||
248 | * statuses_url: Statuses Url |
||
249 | * head: Head |
||
250 | * base: Base |
||
251 | * _links: Links |
||
252 | * @default-fields number,user,title |
||
253 | * @default-string-field number |
||
254 | * @return Consolidation\OutputFormatters\StructuredData\RowsOfFields |
||
255 | */ |
||
256 | public function prFind($projectWithOrg = '', $options = ['as' => 'default', 'format' => 'yaml', 'q' => '']) |
||
257 | { |
||
258 | $api = $this->api($options['as']); |
||
259 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
260 | $q = $options['q']; |
||
261 | |||
262 | if (!empty($q)) { |
||
263 | $q = $q . ' '; |
||
264 | } |
||
265 | $q = $q . 'repo:' . $projectWithOrg; |
||
266 | $searchResults = $api->gitHubAPI()->api('search')->issues($q); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Github\Api\ApiInterface as the method issues() does only exist in the following implementations of said interface: Github\Api\CurrentUser , Github\Api\Enterprise\Stats , Github\Api\Organization , Github\Api\Search .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
267 | $pullRequests = $searchResults['items']; |
||
268 | |||
269 | $pullRequests = $this->keyById($pullRequests, 'number'); |
||
270 | $result = new RowsOfFields($pullRequests); |
||
271 | $this->addTableRenderFunction($result); |
||
272 | |||
273 | return $result; |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * @command org:repos |
||
278 | * @param $org The org to list |
||
279 | * @filter-output |
||
280 | * @field-labels |
||
281 | * url: Url |
||
282 | * id: ID |
||
283 | * owner: Owner |
||
284 | * name: Shortname |
||
285 | * full_name: Name |
||
286 | * private: Private |
||
287 | * fork: Fork |
||
288 | * created_at: Created |
||
289 | * updated_at: Updated |
||
290 | * pushed_at: Pushed |
||
291 | * git_url: Git URL |
||
292 | * ssh_url: SSH URL |
||
293 | * svn_url: SVN URL |
||
294 | * homepage: Homepage |
||
295 | * size: Size |
||
296 | * stargazers_count: Stargazers |
||
297 | * watchers_count: Watchers |
||
298 | * language: Language |
||
299 | * has_issues: Has Issues |
||
300 | * has_projects: Has Projects |
||
301 | * has_downloads: Has Downloads |
||
302 | * has_wiki: Has Wiki |
||
303 | * has_pages: Has Pages |
||
304 | * forks_count: Forks |
||
305 | * archived: Archived |
||
306 | * disabled: Disabled |
||
307 | * open_issues_count: Open Issues |
||
308 | * default_branch: Default Branch |
||
309 | * license: License |
||
310 | * permissions: Permissions |
||
311 | * @default-fields full_name,language,default_branch |
||
312 | * @default-string-field full_name |
||
313 | * |
||
314 | * @return Consolidation\OutputFormatters\StructuredData\RowsOfFields |
||
315 | */ |
||
316 | public function orgRepos($org, $options = ['as' => 'default', 'format' => 'table']) |
||
317 | { |
||
318 | $api = $this->api($options['as']); |
||
319 | $pager = $api->resultPager(); |
||
320 | |||
321 | $repoApi = $api->gitHubAPI()->api('organization'); |
||
322 | $repos = $pager->fetchAll($repoApi, 'repositories', [$org]); |
||
323 | |||
324 | $data = new \Consolidation\OutputFormatters\StructuredData\RowsOfFields($repos); |
||
325 | $this->addTableRenderFunction($data); |
||
326 | |||
327 | return $data; |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * @command repo:info |
||
332 | * @param $projectWithOrg The project to work on, e.g. org/project |
||
333 | * @field-labels |
||
334 | * url: Url |
||
335 | * id: ID |
||
336 | * owner: Owner |
||
337 | * name: Shortname |
||
338 | * full_name: Name |
||
339 | * private: Private |
||
340 | * fork: Fork |
||
341 | * created_at: Created |
||
342 | * updated_at: Updated |
||
343 | * pushed_at: Pushed |
||
344 | * git_url: Git URL |
||
345 | * ssh_url: SSH URL |
||
346 | * svn_url: SVN URL |
||
347 | * homepage: Homepage |
||
348 | * size: Size |
||
349 | * stargazers_count: Stargazers |
||
350 | * watchers_count: Watchers |
||
351 | * language: Language |
||
352 | * has_issues: Has Issues |
||
353 | * has_projects: Has Projects |
||
354 | * has_downloads: Has Downloads |
||
355 | * has_wiki: Has Wiki |
||
356 | * has_pages: Has Pages |
||
357 | * forks_count: Forks |
||
358 | * archived: Archived |
||
359 | * disabled: Disabled |
||
360 | * open_issues_count: Open Issues |
||
361 | * default_branch: Default Branch |
||
362 | * license: License |
||
363 | * permissions: Permissions |
||
364 | * |
||
365 | * @return Consolidation\OutputFormatters\StructuredData\PropertyList |
||
366 | */ |
||
367 | public function repoInfo($projectWithOrg = '', $options = ['as' => 'default', 'format' => 'table']) |
||
368 | { |
||
369 | $api = $this->api($options['as']); |
||
370 | |||
371 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
372 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
373 | |||
374 | $info = $api->gitHubAPI()->api('repo')->show($org, $project); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Github\Api\ApiInterface as the method show() does only exist in the following implementations of said interface: Github\Api\Authorizations , Github\Api\CurrentUser , Github\Api\CurrentUser\Notifications , Github\Api\CurrentUser\PublicKeys , Github\Api\Deployment , Github\Api\Enterprise\License , Github\Api\Enterprise\Stats , Github\Api\Gist\Comments , Github\Api\Gists , Github\Api\GitData\Blobs , Github\Api\GitData\Commits , Github\Api\GitData\References , Github\Api\GitData\Tags , Github\Api\GitData\Trees , Github\Api\Issue , Github\Api\Issue\Comments , Github\Api\Issue\Events , Github\Api\Issue\Labels , Github\Api\Issue\Milestones , Github\Api\Miscellaneous\CodeOfConduct , Github\Api\Miscellaneous\Gitignore , Github\Api\Miscellaneous\Licenses , Github\Api\Organization , Github\Api\Organization\Hooks , Github\Api\Organization\Members , Github\Api\Organization\Projects , Github\Api\Organization\Teams , Github\Api\Project\AbstractProjectApi , Github\Api\Project\Cards , Github\Api\Project\Columns , Github\Api\PullRequest , Github\Api\PullRequest\Comments , Github\Api\PullRequest\Review , Github\Api\Repo , Github\Api\Repository\Assets , Github\Api\Repository\Comments , Github\Api\Repository\Commits , Github\Api\Repository\Contents , Github\Api\Repository\DeployKeys , Github\Api\Repository\Downloads , Github\Api\Repository\Hooks , Github\Api\Repository\Labels , Github\Api\Repository\Pages , Github\Api\Repository\Projects , Github\Api\Repository\Protection , Github\Api\Repository\Releases , Github\Api\Repository\Statuses , Github\Api\User .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
375 | |||
376 | $data = new \Consolidation\OutputFormatters\StructuredData\PropertyList($info); |
||
377 | $this->addTableRenderFunction($data); |
||
378 | |||
379 | return $data; |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * @command repo:default-branch:switch |
||
384 | * @aliases switch-default |
||
385 | */ |
||
386 | public function switchDefaultBranch($projectWithOrg = '', $options = ['as' => 'default', 'branch' => 'main']) |
||
387 | { |
||
388 | $api = $this->api($options['as']); |
||
389 | |||
390 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
391 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
392 | |||
393 | $repoApi = $api->gitHubAPI()->api('repo'); |
||
394 | $info = $repoApi->show($org, $project); |
||
395 | $currentDefault = $info['default_branch']; |
||
396 | $newDefault = $options['branch']; |
||
397 | |||
398 | if ($currentDefault == $newDefault) { |
||
399 | $this->logger->notice("Default branch is already {default}.", ['default' => $currentDefault]); |
||
400 | return; |
||
401 | } |
||
402 | |||
403 | $referencesApi = $api->gitHubAPI()->api('gitData')->references(); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Github\Api\ApiInterface as the method references() does only exist in the following implementations of said interface: Github\Api\GitData .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
404 | |||
405 | // Get the sha of the current HEAD of the current default |
||
406 | $currentDefaultInfo = $referencesApi->show($org, $project, "heads/$currentDefault"); |
||
407 | $currentHeadSha = $currentDefaultInfo['object']['sha']; |
||
408 | |||
409 | // TODO: We could pass $api here, but that would modify the remote url of 'origin'. |
||
410 | // For now we'll use whatever auth is set up for the project at the cwd. |
||
411 | $workingCopy = WorkingCopy::fromDir(getcwd()); |
||
412 | |||
413 | if ($workingCopy->valid() && ($workingCopy->projectWithOrg() == $projectWithOrg)) { |
||
414 | $this->configureDefaultWithWorkingCopy($workingCopy, $currentDefault, $newDefault, $currentHeadSha); |
||
415 | } else { |
||
416 | // Create a new branch for the new default. If it's already there, |
||
417 | // then we'll assume it's at the desired SHA. |
||
418 | try { |
||
419 | $referencesApi->create($org, $project, ['ref' => "refs/heads/$newDefault", 'sha' => $currentHeadSha]); |
||
420 | } catch (\Exception $e) { |
||
421 | $this->logger->notice("Branch {new} already exists; using it as-is.", ['new' => $newDefault]); |
||
422 | } |
||
423 | } |
||
424 | |||
425 | $result = $repoApi->update($org, $project, ['default_branch' => $newDefault]); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
426 | $this->logger->notice("Set default branch to {new}.", ['new' => $newDefault]); |
||
427 | } |
||
428 | |||
429 | protected function configureDefaultWithWorkingCopy($workingCopy, $currentDefault, $newDefault, $currentHeadSha) |
||
430 | { |
||
431 | $statusResult = $workingCopy->status(); |
||
432 | if (!empty($statusResult)) { |
||
433 | throw new \Exception('Working copy not clean; commit, reset or ignore all modified files.'); |
||
434 | } |
||
435 | |||
436 | // TODO: Check to see if new branch already exists, as we do for the API case? |
||
437 | $workingCopy->createBranch($newDefault, $currentHeadSha); |
||
438 | |||
439 | $fixupList = ['README.md', '.travis.yml', 'composer.json', '.circleci/config.yml']; |
||
440 | $alteredList = []; |
||
441 | foreach ($fixupList as $file) { |
||
442 | if (file_exists($file)) { |
||
443 | $contents = file_get_contents($file); |
||
444 | $altered = str_replace($currentDefault, $newDefault, $contents); |
||
445 | if ($altered != $contents) { |
||
446 | file_put_contents($file, $altered); |
||
447 | $alteredList[] = $file; |
||
448 | } |
||
449 | } |
||
450 | } |
||
451 | |||
452 | $statusResult = $workingCopy->status(); |
||
453 | if (!empty($statusResult)) { |
||
454 | passthru('git diff'); |
||
455 | |||
456 | // If we modified composer.json, update composer.lock |
||
457 | if (in_array('composer.json', $alteredList)) { |
||
458 | passthru('composer update'); |
||
459 | } |
||
460 | |||
461 | $workingCopy->add('.'); |
||
462 | |||
463 | $workingCopy->commit("Change references to old default branch '$currentDefault' to new default branch '$newDefault'"); |
||
464 | } |
||
465 | |||
466 | $workingCopy->push('origin', $newDefault); |
||
467 | } |
||
468 | |||
469 | /** |
||
470 | * @command pr:show |
||
471 | * @field-labels |
||
472 | * url: Url |
||
473 | * id: ID |
||
474 | * node_id: Node ID |
||
475 | * html_url: HTML Url |
||
476 | * diff_url: Diff Url |
||
477 | * patch_url: Patch Url |
||
478 | * issue_url: Issue Url |
||
479 | * number: Number |
||
480 | * state: State |
||
481 | * locked: Locked |
||
482 | * title: Title |
||
483 | * user: User |
||
484 | * body: Boday |
||
485 | * created_at: Created |
||
486 | * updated_at: Updated |
||
487 | * closed_at: Closed |
||
488 | * mergeable: Mergeable |
||
489 | * mergeable_state: Mergable State |
||
490 | * merged_at: Merged |
||
491 | * merge_commit_sha: Merge Commit |
||
492 | * assignee: Assignee |
||
493 | * assignees: Assignees |
||
494 | * requested_reviewers: Requested Reviewers |
||
495 | * requested_teams: Requested Teams |
||
496 | * labels: Labels |
||
497 | * milestone: Milestone |
||
498 | * commits_url: Commit Url |
||
499 | * review_comments_url: Review Comments Url |
||
500 | * review_comment_url: Review Comment Url |
||
501 | * comments_url: Comments Url |
||
502 | * statuses_url: Statuses Url |
||
503 | * head: Head |
||
504 | * base: Base |
||
505 | * _links: Links |
||
506 | * @return Consolidation\OutputFormatters\StructuredData\PropertyList |
||
507 | */ |
||
508 | public function prShow($projectWithOrg = '', $number = '', $options = ['as' => 'default', 'format' => 'table']) |
||
509 | { |
||
510 | if (empty($number) && preg_match('#^[0-9]*$#', $projectWithOrg)) { |
||
511 | $number = $projectWithOrg; |
||
512 | $projectWithOrg = ''; |
||
513 | } |
||
514 | $api = $this->api($options['as']); |
||
515 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
516 | |||
517 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
518 | |||
519 | $pullRequest = $api->gitHubAPI()->api('pull_request')->show($org, $project, $number); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Github\Api\ApiInterface as the method show() does only exist in the following implementations of said interface: Github\Api\Authorizations , Github\Api\CurrentUser , Github\Api\CurrentUser\Notifications , Github\Api\CurrentUser\PublicKeys , Github\Api\Deployment , Github\Api\Enterprise\License , Github\Api\Enterprise\Stats , Github\Api\Gist\Comments , Github\Api\Gists , Github\Api\GitData\Blobs , Github\Api\GitData\Commits , Github\Api\GitData\References , Github\Api\GitData\Tags , Github\Api\GitData\Trees , Github\Api\Issue , Github\Api\Issue\Comments , Github\Api\Issue\Events , Github\Api\Issue\Labels , Github\Api\Issue\Milestones , Github\Api\Miscellaneous\CodeOfConduct , Github\Api\Miscellaneous\Gitignore , Github\Api\Miscellaneous\Licenses , Github\Api\Organization , Github\Api\Organization\Hooks , Github\Api\Organization\Members , Github\Api\Organization\Projects , Github\Api\Organization\Teams , Github\Api\Project\AbstractProjectApi , Github\Api\Project\Cards , Github\Api\Project\Columns , Github\Api\PullRequest , Github\Api\PullRequest\Comments , Github\Api\PullRequest\Review , Github\Api\Repo , Github\Api\Repository\Assets , Github\Api\Repository\Comments , Github\Api\Repository\Commits , Github\Api\Repository\Contents , Github\Api\Repository\DeployKeys , Github\Api\Repository\Downloads , Github\Api\Repository\Hooks , Github\Api\Repository\Labels , Github\Api\Repository\Pages , Github\Api\Repository\Projects , Github\Api\Repository\Protection , Github\Api\Repository\Releases , Github\Api\Repository\Statuses , Github\Api\User .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
520 | |||
521 | $result = new PropertyList($pullRequest); |
||
522 | $this->addTableRenderFunction($result); |
||
523 | |||
524 | return $result; |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * @command pr:statuses |
||
529 | * @field-labels |
||
530 | * url: Url |
||
531 | * id: ID |
||
532 | * state: State |
||
533 | * description: Description |
||
534 | * node_id: Node ID |
||
535 | * context: Context |
||
536 | * avatar_url: Avatar URL |
||
537 | * target_url: Target URL |
||
538 | * creator: Creator |
||
539 | * created_at: Created |
||
540 | * updated_at: Updated |
||
541 | * @default-fields id,creator,state,description |
||
542 | * @default-string-field description |
||
543 | * @return Consolidation\OutputFormatters\StructuredData\RowsOfFields |
||
544 | */ |
||
545 | View Code Duplication | public function prStatuses($projectWithOrg = '', $number = '', $options = ['as' => 'default', 'format' => 'yaml']) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
546 | { |
||
547 | if (empty($number) && preg_match('#^[0-9]*$#', $projectWithOrg)) { |
||
548 | $number = $projectWithOrg; |
||
549 | $projectWithOrg = ''; |
||
550 | } |
||
551 | $api = $this->api($options['as']); |
||
552 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
553 | |||
554 | $pullRequestStatus = $api->prStatuses($projectWithOrg, $number); |
||
555 | |||
556 | $result = new RowsOfFields($pullRequestStatus); |
||
557 | $this->addTableRenderFunction($result); |
||
558 | |||
559 | return $result; |
||
560 | } |
||
561 | |||
562 | /** |
||
563 | * @command pr:list |
||
564 | * @param $projectWithOrg The project to work on, e.g. org/project |
||
565 | * @filter-output |
||
566 | * @field-labels |
||
567 | * url: Url |
||
568 | * id: ID |
||
569 | * node_id: Node ID |
||
570 | * html_url: HTML Url |
||
571 | * diff_url: Diff Url |
||
572 | * patch_url: Patch Url |
||
573 | * issue_url: Issue Url |
||
574 | * number: Number |
||
575 | * state: State |
||
576 | * locked: Locked |
||
577 | * title: Title |
||
578 | * user: User |
||
579 | * body: Boday |
||
580 | * created_at: Created |
||
581 | * updated_at: Updated |
||
582 | * closed_at: Closed |
||
583 | * merged_at: Merged |
||
584 | * merge_commit_sha: Merge Commit |
||
585 | * assignee: Assignee |
||
586 | * assignees: Assignees |
||
587 | * requested_reviewers: Requested Reviewers |
||
588 | * requested_teams: Requested Teams |
||
589 | * labels: Labels |
||
590 | * milestone: Milestone |
||
591 | * commits_url: Commit Url |
||
592 | * review_comments_url: Review Comments Url |
||
593 | * review_comment_url: Review Comment Url |
||
594 | * comments_url: Comments Url |
||
595 | * statuses_url: Statuses Url |
||
596 | * head: Head |
||
597 | * base: Base |
||
598 | * _links: Links |
||
599 | * @default-fields number,user,title |
||
600 | * @default-string-field number |
||
601 | * @return Consolidation\OutputFormatters\StructuredData\RowsOfFields |
||
602 | */ |
||
603 | public function prList($projectWithOrg = '', $options = ['state' => 'open', 'as' => 'default', 'format' => 'table']) |
||
604 | { |
||
605 | $api = $this->api($options['as']); |
||
606 | $projectWithOrg = $this->projectWithOrg($projectWithOrg); |
||
607 | |||
608 | list($org, $project) = explode('/', $projectWithOrg, 2); |
||
609 | |||
610 | $pullRequests = $api->gitHubAPI()->api('pull_request')->all($org, $project, ['state' => $options['state']]); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Github\Api\ApiInterface as the method all() does only exist in the following implementations of said interface: Github\Api\Authorizations , Github\Api\CurrentUser\Emails , Github\Api\CurrentUser\Followers , Github\Api\CurrentUser\Memberships , Github\Api\CurrentUser\Notifications , Github\Api\CurrentUser\PublicKeys , Github\Api\CurrentUser\Starring , Github\Api\CurrentUser\Watchers , Github\Api\Deployment , Github\Api\Enterprise\Stats , Github\Api\Gist\Comments , Github\Api\Gists , Github\Api\GitData\References , Github\Api\GitData\Tags , Github\Api\Issue , Github\Api\Issue\Comments , Github\Api\Issue\Events , Github\Api\Issue\Labels , Github\Api\Issue\Milestones , Github\Api\Issue\Timeline , Github\Api\Miscellaneous\CodeOfConduct , Github\Api\Miscellaneous\Emojis , Github\Api\Miscellaneous\Gitignore , Github\Api\Miscellaneous\Licenses , Github\Api\Notification , Github\Api\Organization , Github\Api\Organization\Hooks , Github\Api\Organization\Members , Github\Api\Organization\Projects , Github\Api\Organization\Teams , Github\Api\Project\Cards , Github\Api\Project\Columns , Github\Api\PullRequest , Github\Api\PullRequest\Comments , Github\Api\PullRequest\Review , Github\Api\PullRequest\ReviewRequest , Github\Api\Repo , Github\Api\Repository\Assets , Github\Api\Repository\Collaborators , Github\Api\Repository\Comments , Github\Api\Repository\Commits , Github\Api\Repository\DeployKeys , Github\Api\Repository\Downloads , Github\Api\Repository\Forks , Github\Api\Repository\Hooks , Github\Api\Repository\Labels , Github\Api\Repository\Projects , Github\Api\Repository\Releases , Github\Api\Repository\Stargazers , Github\Api\User .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
611 | |||
612 | $pullRequests = $this->keyById($pullRequests, 'number'); |
||
613 | |||
614 | $result = new RowsOfFields($pullRequests); |
||
615 | $this->addTableRenderFunction($result); |
||
616 | |||
617 | return $result; |
||
618 | } |
||
619 | |||
620 | protected function addTableRenderFunction($data) |
||
621 | { |
||
622 | $data->addRendererFunction( |
||
623 | function ($key, $cellData, FormatterOptions $options, $rowData) { |
||
0 ignored issues
–
show
|
|||
624 | if (empty($cellData)) { |
||
625 | return ''; |
||
626 | } |
||
627 | if (is_array($cellData)) { |
||
628 | if ($key == 'permissions') { |
||
629 | return implode(',', array_filter(array_keys($cellData))); |
||
630 | } |
||
631 | foreach (['login', 'label', 'name'] as $k) { |
||
632 | if (isset($cellData[$k])) { |
||
633 | return $cellData[$k]; |
||
634 | } |
||
635 | } |
||
636 | // TODO: simplify |
||
637 | // assignees |
||
638 | // requested_reviewers |
||
639 | // requested_teams |
||
640 | // labels |
||
641 | // _links |
||
642 | return json_encode($cellData, true); |
||
643 | } |
||
644 | if (!is_string($cellData)) { |
||
645 | return var_export($cellData, true); |
||
646 | } |
||
647 | return $cellData; |
||
648 | } |
||
649 | ); |
||
650 | } |
||
651 | |||
652 | protected function keyById($data, $field) |
||
653 | { |
||
654 | return |
||
655 | array_column( |
||
656 | array_map( |
||
657 | function ($k) use ($data, $field) { |
||
658 | return [$data[$k][$field], $data[$k]]; |
||
659 | }, |
||
660 | array_keys($data) |
||
661 | ), |
||
662 | 1, |
||
663 | 0 |
||
664 | ); |
||
665 | } |
||
666 | |||
667 | protected function api($as = 'default') |
||
668 | { |
||
669 | $api = new HubphAPI($this->getConfig()); |
||
670 | $api->setAs($as); |
||
671 | |||
672 | return $api; |
||
673 | } |
||
674 | } |
||
675 |
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.