Completed
Pull Request — master (#168)
by Deven
03:45
created

GithubApiComponent::getIssue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 10
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 4
crap 2
1
<?php
2
/* vim: set expandtab sw=4 ts=4 sts=4: */
3
4
/**
5
 * Github api component handling comunication with github.
6
 *
7
 * phpMyAdmin Error reporting server
8
 * Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
9
 *
10
 * Licensed under The MIT License
11
 * For full copyright and license information, please see the LICENSE.txt
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
15
 * @license   https://opensource.org/licenses/mit-license.php MIT License
16
 *
17
 * @see      https://www.phpmyadmin.net/
18
 */
19
20
namespace App\Controller\Component;
21
22
use Cake\Controller\Component;
23
use Cake\Routing\Router;
24
25
/**
26
 * Github api component handling comunication with github.
27
 */
28
class GithubApiComponent extends Component
29
{
30
    /**
31
     * perform an api request given a path, the data to send, the method and whether
32
     * or not to return a status.
33
     *
34
     * @param string $path         the api path to preform the request to
35
     * @param array  $data         the data to send in the request. This works with both GET
36
     *                             and Post requests
37
     * @param string $method       the method type of the request
38
     * @param bool   $returnStatus whether to return the status code with the
39
     *                             request
40
     * @param mixed  $access_token
41
     *
42
     * @return array the returned response decoded and optionally the status code,
43
     *               see GithubApiComponent::sendRequest()
44
     *
45
     * @see GithubApiComponent::sendRequest()
46
     */
47
    public function apiRequest(
48
        $path = '',
49
        $data = array(),
50
        $method = 'GET',
51
        $returnStatus = false,
52
        $access_token = ''
53
    ) {
54
        $path = 'https://api.github.com/' . $path;
55
        if (strtoupper($method) === 'GET') {
56
            $path .= '?' . http_build_query($data);
57
            $data = array();
58
        }
59
60
        return $this->sendRequest($path, $data, $method, $returnStatus, $access_token);
61
    }
62
63
    /**
64
     * retrieve an access token using a code that has been authorized by a user.
65
     *
66
     * @param string $code the code returned by github to the callback url
67
     *
68
     * @return string the access token
69
     */
70
    public function getAccessToken($code)
71
    {
72
        $url = 'https://github.com/login/oauth/access_token';
73
        $data = array_merge(
74
            $this->githubConfig,
75
            array(
76
                'code' => $code,
77
            )
78
        );
79
        $decodedResponse = $this->sendRequest($url, http_build_query($data), 'POST');
80
81
        return $decodedResponse['access_token'];
82
    }
83
84
    /**
85
     * retrieve the github info stored on a user by his access token.
86
     *
87
     * @param string $accessToken the access token belonging to the user being
88
     *                            requested
89
     *
90
     * @return Arrray the github info returned by github as an associative array
91
     */
92
    public function getUserInfo($accessToken)
93
    {
94
        $data = array(
95
            'access_token' => $accessToken,
96
        );
97
98
        return $this->apiRequest('user', $data, 'GET', true);
99
    }
100
101
    /**
102
     * perform an http request using curl given a url, the post data to send, the
103
     * request method and whether or not to return a status.
104
     *
105
     * @param string $url          the url to preform the request to
106
     * @param array  $data         the post data to send in the request. This only works with POST requests. GET requests need the data appended in the url.
107
     *                             with POST requests. GET requests need the data appended
108
     *                             in the url.
109
     * @param string $method       the method type of the request
110
     * @param bool   $returnCode   whether to return the status code with the
111
     *                             request
112
     * @param mixed  $access_token
113
     *
114
     * @return array the returned response decoded and optionally the status code,
115
     *               eg: array($decodedResponse, $statusCode) or just $decodedResponse
116
     */
117
    public function sendRequest(
118
        $url,
119
        $data,
120
        $method,
121
        $returnCode = false,
122
        $access_token = ''
123
    ) {
124
        $curlHandle = curl_init($url);
125
        curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, $method);
126
        $header = array('Accept: application/json');
127
        if (isset($access_token) && $access_token != '') {
128
            $header[] = 'Authorization: token ' . $access_token;
129
        }
130
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $header);
131
        curl_setopt($curlHandle, CURLOPT_USERAGENT, 'phpMyAdmin - Error Reporting Server');
132
        curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $data);
133
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
134
        $response = curl_exec($curlHandle);
135
        $decodedResponse = json_decode($response, true);
136
        if ($returnCode) {
137
            $status = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);
138
139
            return array($decodedResponse, $status);
140
        }
141
142
        return $decodedResponse;
143
    }
144
145
    /**
146
     * generate the url to redirect the user to for authorization given the
147
     * requested scope.
148
     *
149
     * @param string $scope the api scope for the user to authorize
150
     *
151
     * @return string the generated url to redirect the user to
152
     */
153
    public function getRedirectUrl($scope = null)
154
    {
155
        $url = 'https://github.com/login/oauth/authorize';
156
        $data = array(
157
            'client_id' => $this->githubConfig['client_id'],
158
            'redirect_uri' => Router::url(
159
                array(
160
                    'controller' => 'developers',
161
                    'action' => 'callback',
162
                ), true
163
            ),
164
            'scope' => $scope,
165
        );
166
167
        $url .= '?' . http_build_query($data);
168
169
        return $url;
170
    }
171
172
    /**
173
     * Check if a user can commit to a rep.
174
     *
175
     * @param string $username the username to check
176
     * @param string $repoPath the repo path of the repo to check for
177
     *
178
     * @return bool true if the user is a collaborator and false if they arent
179
     */
180
    public function canCommitTo($username, $repoPath, $access_token)
181
    {
182
        list(, $status) = $this->apiRequest(
183
            "repos/$repoPath/collaborators/$username",
184
            array(),
185
            'GET',
186
            true,
187
            $access_token
188
        );
189
190
        return $status === 204;
191
    }
192
193
    /**
194
     * make api request for github issue creation.
195
     *
196
     * @param string $repoPath
197
     * @param array  $data         issue details
198
     * @param string $access_token
199
     */
200
    public function createIssue($repoPath, $data, $access_token)
201
    {
202
        return $this->apiRequest(
203
            "repos/$repoPath/issues",
204
            json_encode($data),
205
            'POST',
206
            true,
207
            $access_token
208
        );
209
    }
210
211
    /**
212
     * make api request for github comment creation.
213
     *
214
     * @param string $repoPath
215
     * @param array  $data
216
     * @param int    $issueNumber
217
     * @param string $access_token
218
     */
219
    public function createComment($repoPath, $data, $issueNumber, $access_token)
220
    {
221
        return $this->apiRequest(
222
            "repos/$repoPath/issues/$issueNumber/comments",
223
            json_encode($data),
224
            'POST',
225
            true,
226
            $access_token
227
        );
228
    }
229
230
    /**
231
     * Make API request for getting Github issue's status
232
     *
233
     * @param string $repoPath
234
     * @param array  $data
235
     * @param int    $issueNumber
236
     * @param string $access_token
237
     */
238
    public function getIssue($repoPath, $data, $issueNumber, $access_token)
239
    {
240
        return $this->apiRequest(
241
            "repos/$repoPath/issues/$issueNumber",
242
            $data,
243
            'GET',
244
            true,
245
            $access_token
246
        );
247
    }
248
249
}
250