Completed
Push — master ( 8c1622...0ad19e )
by Greg
328:48
created

HubphAPI::stopLogging()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Hubph;
4
5
use Consolidation\Config\ConfigInterface;
6
7
class HubphAPI
8
{
9
    protected $config;
10
    protected $token;
11
    protected $gitHubAPI;
12
    protected $as = 'default';
13
14
    /**
15
     * HubphAPI constructor
16
     */
17
    public function __construct(ConfigInterface $config)
18
    {
19
        $this->config = $config;
20
    }
21
22
    public function startLogging($filename)
23
    {
24
        $this->stopLogging();
25
        $this->eventLogger = new EventLogger($filename);
0 ignored issues
show
Bug introduced by
The property eventLogger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
26
        $this->eventLogger->start();
27
    }
28
29
    public function stopLogging()
30
    {
31
        if ($this->eventLogger) {
32
            $this->eventLogger->stop();
33
        }
34
        $this->eventLogger = null;
35
    }
36
37
    public function setAs($as)
38
    {
39
        if ($as != $this->as) {
40
            $this->as = $as;
41
            $this->token = false;
42
            $this->gitHubAPI = false;
43
        }
44
    }
45
46
    public function whoami()
47
    {
48
        $gitHubAPI = $this->gitHubAPI();
49
        $authenticated = $gitHubAPI->api('current_user')->show();
0 ignored issues
show
Bug introduced by
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\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\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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
50
        return $authenticated;
51
    }
52
53
    public function prCreate($org, $project, $title, $body, $base, $head)
54
    {
55
        $params = [
56
            'title' => $title,
57
            'body' => $body,
58
            'base' => $base,
59
            'head' => $head,
60
        ];
61
        $response = $this->gitHubAPI()->api('pull_request')->create($org, $project, $params);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Github\Api\ApiInterface as the method create() does only exist in the following implementations of said interface: Github\Api\Authorizations, Github\Api\CurrentUser\PublicKeys, Github\Api\Deployment, 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\Labels, Github\Api\Issue\Milestones, Github\Api\Organization\Hooks, 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\Comments, Github\Api\Repository\Contents, Github\Api\Repository\DeployKeys, Github\Api\Repository\Forks, Github\Api\Repository\Hooks, Github\Api\Repository\Labels, Github\Api\Repository\Projects, Github\Api\Repository\Releases, Github\Api\Repository\Statuses.

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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
62
        $this->logEvent(__FUNCTION__, [$org, $project], $params, $response);
63
        return $this;
64
    }
65
66
    public function prClose($org, $project, $number)
67
    {
68
        foreach ((array)$number as $n) {
69
            $gitHubAPI = $this->gitHubAPI();
70
            $gitHubAPI->api('pull_request')->update($org, $project, $n, ['state' => 'closed']);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Github\Api\ApiInterface as the method update() does only exist in the following implementations of said interface: Github\Api\Authorizations, Github\Api\CurrentUser, Github\Api\Gist\Comments, Github\Api\Gists, Github\Api\GitData\References, Github\Api\Issue, Github\Api\Issue\Comments, Github\Api\Issue\Labels, Github\Api\Issue\Milestones, Github\Api\Organization, Github\Api\Organization\Hooks, 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\Repo, Github\Api\Repository\Comments, Github\Api\Repository\Contents, Github\Api\Repository\DeployKeys, Github\Api\Repository\Hooks, Github\Api\Repository\Labels, Github\Api\Repository\Projects, Github\Api\Repository\Protection.

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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
71
        }
72
    }
73
74
    public function prCheck($projectWithOrg, $vids)
75
    {
76
        // Find all of the PRs that contain any vid
77
        $existingPRs = $this->existingPRs($projectWithOrg, $vids);
78
79
        // Check to see if there are PRs matching all of the vids/vvals.
80
        // If so, exit with a message and do nothing.
81
        $titles = $existingPRs->titles();
82
        if ($vids->allExist($titles)) {
83
            return [2, "Pull requests already exist; nothing more to do."];
84
        }
85
86
        // Check to see if there are PRs matching SOME of the vids (with
87
        // or without the matching vvals).  If so, close all that match.
88
        if ($existingPRs->isEmpty()) {
89
            return [0, "No open pull requests that need to be closed."];
90
        }
91
92
        return [0, $existingPRs->prNumbers()];
93
    }
94
95
    public function addTokenAuthentication($url)
96
    {
97
        $token = $this->gitHubToken();
98
        if (!$token) {
99
            return $url;
100
        }
101
        $projectAndOrg = $this->projectAndOrgFromUrl($url);
102
        return "https://{$token}:[email protected]/{$projectAndOrg}.git";
103
    }
104
105 View Code Duplication
    protected function projectAndOrgFromUrl($remote)
0 ignored issues
show
Duplication introduced by
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.

Loading history...
106
    {
107
        $remote = preg_replace('#^git@[^:]*:#', '', $remote);
108
        $remote = preg_replace('#^[^:]*://[^/]*/#', '', $remote);
109
        $remote = preg_replace('#\.git$#', '', $remote);
110
111
        return $remote;
112
    }
113
114
    protected function existingPRs($projectWithOrg, $vids)
115
    {
116
        $preamble = $vids->getPreamble();
117
        $q = "repo:$projectWithOrg in:title is:pr state:open $preamble";
118
        $result = new PullRequests();
119
        $gitHubAPI = $this->gitHubAPI();
120
        $searchResults = $gitHubAPI->api('search')->issues($q);
0 ignored issues
show
Bug introduced by
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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
121
        $result->addSearchResults($searchResults, $vids->pattern());
122
123
        return $result;
124
    }
125
126
    public function allPRs($projectWithOrg)
127
    {
128
        $q = "repo:$projectWithOrg in:title is:pr state:open";
129
        $result = new PullRequests();
130
        $searchResults = $this->gitHubAPI()->api('search')->issues($q);
0 ignored issues
show
Bug introduced by
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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
131
        $result->addSearchResults($searchResults);
132
133
        return $result;
134
    }
135
136
    /**
137
     * Pass an event of note to the event logger
138
     * @param string $event_name
139
     * @param array $args
140
     * @param array $params
141
     * @param array $response
142
     */
143
    protected function logEvent($event_name, $args, $params, $response)
144
    {
145
        if ($this->eventLogger) {
146
            $this->eventLogger->log($event_name, $args, $params, $response);
147
        }
148
    }
149
150
    /**
151
     * Authenticate and then return the gitHub API object.
152
     */
153
    public function gitHubAPI()
154
    {
155
        if (!$this->gitHubAPI) {
156
            $token = $this->gitHubToken();
157
158
            $this->gitHubAPI = new \Github\Client();
159
            $this->gitHubAPI->authenticate($token, null, \Github\Client::AUTH_HTTP_TOKEN);
160
        }
161
        return $this->gitHubAPI;
162
    }
163
164
    /**
165
     * Look up the GitHub token set either via environment variable or in the
166
     * auth-token cache directory.
167
     */
168
    public function gitHubToken()
169
    {
170
        if (!$this->token) {
171
            $this->token = $this->getGitHubToken();
172
        }
173
        return $this->token;
174
    }
175
176
    protected function getGitHubToken()
177
    {
178
        $as = $this->as;
179
        if ($as == 'default') {
180
            $as = $this->getConfig()->get("github.default-user");
181
        }
182
        $github_token_cache = $this->getConfig()->get("github.personal-auth-token.$as.path");
183
        if (file_exists($github_token_cache)) {
184
            $token = trim(file_get_contents($github_token_cache));
185
            putenv("GITHUB_TOKEN=$token");
186
        } else {
187
            $token = getenv('GITHUB_TOKEN');
188
        }
189
190
        return $token;
191
    }
192
193
    protected function getConfig()
194
    {
195
        return $this->config;
196
    }
197
}
198