Completed
Push — master ( dbac1a...90c739 )
by Michal
11s
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)
181
    {
182
        list(, $status) = $this->
183
                apiRequest("repos/$repoPath/collaborators/$username",
184
                http_build_query(array()), 'GET', true);
185
186
        return $status === 204;
187
    }
188
189
    /**
190
     * make api request for github issue creation.
191
     *
192
     * @param string $repoPath
193
     * @param array  $data         issue details
194
     * @param string $access_token
195
     */
196
    public function createIssue($repoPath, $data, $access_token)
197
    {
198
        return $this->apiRequest(
199
            "repos/$repoPath/issues",
200
            json_encode($data),
201
            'POST',
202
            true,
203
            $access_token
204
        );
205
    }
206
207
    /**
208
     * make api request for github comment creation.
209
     *
210
     * @param string $repoPath
211
     * @param array  $data
212
     * @param int    $issueNumber
213
     * @param string $access_token
214
     */
215
    public function createComment($repoPath, $data, $issueNumber, $access_token)
216
    {
217
        return $this->apiRequest(
218
            "repos/$repoPath/issues/$issueNumber/comments",
219
            json_encode($data),
220
            'POST',
221
            true,
222
            $access_token
223
        );
224
    }
225
226
    /**
227
     * Make API request for getting Github issue's status
228
     *
229
     * @param string $repoPath
230
     * @param array  $data
231
     * @param int    $issueNumber
232
     * @param string $access_token
233
     */
234
    public function getIssue($repoPath, $data, $issueNumber, $access_token)
235
    {
236
        return $this->apiRequest(
237
            "repos/$repoPath/issues/$issueNumber",
238
            $data,
239
            'GET',
240
            true,
241
            $access_token
242
        );
243
    }
244
245
}
246