Passed
Push — master ( b00485...b911e4 )
by Goffy
03:26
created

class/Github/GithubClient.php (6 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace XoopsModules\Wggithub\Github;
6
7
/*
8
 * You may not change or alter any portion of this comment or credits
9
 * of supporting developers from this source code or any supporting source code
10
 * which is considered copyrighted (c) material of the original comment or credit authors.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 */
16
/**
17
 * @copyright    XOOPS Project https://xoops.org/
18
 * @license      GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
19
 * @since
20
 * @author       Goffy - XOOPS Development Team
21
 */
22
23
use XoopsModules\Wggithub;
24
use XoopsModules\Wggithub\{
25
    Helper,
26
    Constants,
27
    Github
28
};
29
30
/**
31
 * Class GithubClient
32
 */
33
class GithubClient extends Api
34
{
35
    /**
36
     * @var string
37
     */
38
    public const BASE_URL = 'https://api2.github.com/';
39
40
    /**
41
     * @var string
42
     */
43
    //public $userAuth = 'myusername';
44
45
    /**
46
     * @var string
47
     */
48
    public $tokenAuth = 'mytoken';
49
50
    /**
51
     * @var object
52
     */
53
    private $helper = null;
54
55
    /**
56
     * Constructor
57
     *
58
     * @param null
59
     */
60
    public function __construct()
61
    {
62
        $this->helper = \XoopsModules\Wggithub\Helper::getInstance();
63
        $this->getSetting();
64
    }
65
66
    /**
67
     * @static function &getInstance
68
     *
69
     * @param null
70
     * @return GitHubClient of Api
71
     */
72
    public static function getInstance()
73
    {
74
        static $instance = false;
75
        if (!$instance) {
76
            $instance = new self();
77
        }
78
79
        return $instance;
80
    }
81
82
    public function testApi1($url) {
83
        $api = new Github\Api;
84
        $response = $api->get(static::BASE_URL . $url);
85
        $data = $api->decode($response);
86
        
87
        return $data;
88
    }
89
90
    public function testApi2($url) {
91
        $api = new Github\Api;
92
93
        $token = new Github\OAuth\Token('{myKey}', 'bearer', ['repo', 'user', 'public_repo']);
94
        $api->setToken($token);
95
        $response = $api->get(static::BASE_URL . $url);
96
97
        $data = $api->decode($response);
98
99
        /*
100
        $api = new Github\Api;
101
102
        $request = $api->createRequest('GET', $url, [], [], '');
103
        $response = $api->request($request);
104
        $data = (array)$api->decode($response);
105
        */
106
107
        return $data;
108
    }
109
110
    /**
111
     * Get repositories of given user
112
     *
113
     * @param     $username
114
     * @param int $per_page
115
     * @param int $page
116
     * @return array
117
     */
118
    public function getUserRepositories($username, $per_page = 100, $page = 1)
119
    {
120
        $url = static::BASE_URL . 'users/' . \rawurlencode($username) . '/repos?per_page=' . $per_page . '&page=' . $page;
121
122
        return $this->_get($url);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_get($url) also could return the type boolean which is incompatible with the documented return type array.
Loading history...
123
    }
124
125
    /**
126
     * Get repositories of given organisation
127
     *
128
     * @param     $org
129
     * @param int $per_page
130
     * @param int $page
131
     * @return array
132
     */
133
    public function getOrgRepositories($org, $per_page = 100, $page = 1)
134
    {
135
        $url = static::BASE_URL . 'orgs/' . \rawurlencode($org) . '/repos?per_page=' . $per_page . '&page=' . $page;
136
137
        return $this->_get($url);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_get($url) also could return the type boolean which is incompatible with the documented return type array.
Loading history...
138
    }
139
140
    /**
141
     * Get the readme content for a repository by its username and repository name.
142
     *
143
     * @param string $username   the user who owns the repository
144
     * @param string $repository the name of the repository
145
     * @return string|array the readme content
146
     */
147
    public function getReadme($username, $repository)
148
    {
149
        $url = static::BASE_URL . 'repos/' . \rawurlencode($username) . '/' . \rawurlencode($repository) . '/readme';
150
151
        return $this->_get($url, true);
152
    }
153
154
    /**
155
     * Get all releases
156
     *
157
     * @param string $username   the user who owns the repository
158
     * @param string $repository the name of the repository
159
     * @return array
160
     */
161
    public function getReleases($username, $repository)
162
    {
163
        $url = static::BASE_URL . 'repos/' . $username . '/' . $repository . '/releases';
164
165
        return $this->_get($url, true);
166
    }
167
168
    /**
169
     * Get latest release
170
     *
171
     * @param string $username   the user who owns the repository
172
     * @param string $repository the name of the repository
173
     * @param bool   $prerelease
174
     * @return array
175
     */
176
    public function getLatestRelease($username, $repository, $prerelease = false)
177
    {
178
        //function currently not used
179
        if ($prerelease) {
180
            $url = static::BASE_URL . 'repos/' . $username . '/' . $repository . '/releases';
181
        } else {
182
            $url = static::BASE_URL . 'repos/' . $username . '/' . $repository . '/releases/latest';
183
        }
184
        $result = $this->_get($url);
185
186
        if (\is_array($result) && \array_key_exists('error_code', $result)) {
187
            //TODO: improve error handling
188
            echo $result['message'];
189
            die;
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
190
        }
191
        if ($prerelease) {
192
            if (\is_array($result)) {
193
                return $result[0];
194
            } else {
195
                return [];
196
            }
197
        }
198
199
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type boolean which is incompatible with the documented return type array.
Loading history...
200
    }
201
    
202
    /**
203
     * Get content of repository
204
     *
205
     * @param  $username
206
     * @param  $repository
207
     * @return array
208
     */
209
    public function getRepositoryContent($username, $repository)
210
    {
211
        $url = static::BASE_URL . 'repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents';
212
213
        return $this->_get($url);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_get($url) also could return the type boolean which is incompatible with the documented return type array.
Loading history...
214
    }
215
216
    /**
217
     * Get github content
218
     *
219
     * @param      $url
220
     * @param bool $skipError
221
     * @return array|bool
222
     */
223
    public function _get($url, $skipError = false)
224
    {
225
        $error = false;
226
        $errMsg = '';
227
228
        $logsHandler = $this->helper->getHandler('Logs');
229
        $logsHandler->updateTableLogs(Constants::LOG_TYPE_REQUEST, $url, 'START');
230
        $api = new Github\Api;
231
        $token = new Github\OAuth\Token($this->tokenAuth, 'bearer', ['repo', 'user', 'public_repo']);
232
        $api->setToken($token);
233
        $response = $api->get($url);
234
        $code = $response->getCode();
235
        if (\in_array($code, [200, 201], true)) {
236
            $logsHandler->updateTableLogs(Constants::LOG_TYPE_REQUEST, $url, 'OK');
237
        } else {
238
            if ($skipError) {
239
                $logsHandler->updateTableLogs(Constants::LOG_TYPE_ERROR, $errMsg, 'Skipped');
240
                return false;
241
            } else {
242
                $error = true;
243
                $errMsg = $response->getContent();
244
                $logsHandler->updateTableLogs(Constants::LOG_TYPE_ERROR, $errMsg, 'ERROR ' . $code);
245
            }
246
        }
247
        if ($error) {
248
            //catch common errors
249
            switch ($code) {
250
                case 401:
251
                    $message = \_MA_WGGITHUB_READGH_ERROR_API_401;
252
                    break;
253
                case 403:
254
                    /*if (\strpos($errMsg, 'API rate limit exceeded') > 0) {$GLOBALS['xoopsTpl']->assign('apiexceed', true);}*/
255
                    $message = \_MA_WGGITHUB_READGH_ERROR_API_403;
256
                    break;
257
                case 404:
258
                    $message = \_MA_WGGITHUB_READGH_ERROR_API_404;
259
                    break;
260
                case 405:
261
                    $message = \_MA_WGGITHUB_READGH_ERROR_API_405;
262
                    break;
263
                case 0:
264
                default:
265
                    $message = \_MA_WGGITHUB_READGH_ERROR_API . '(' .$code . ' - ' .  $errMsg . ')';
266
                    break;
267
            }
268
            redirect_header('index.php?op=api_error&amp;message='. $message . '&amp;url='. $url, 5, $message);
269
            //throw new \RuntimeException('"' . $message . '"');
270
        } else {
271
            $data = (array)$api->decode($response);
272
        }
273
274
        return $data;
275
    }
276
277
    /**
278
     * Execute update of repositories and all related tables
279
     * @param string $dirName
280
     * @return bool
281
     */
282
    public function executeUpdate($dirName = '')
283
    {
284
        $helper = Helper::getInstance();
285
        $directoriesHandler = $helper->getHandler('Directories');
286
        $repositoriesHandler = $helper->getHandler('Repositories');
287
        $releasesHandler = $helper->getHandler('Releases');
288
        $readmesHandler = $helper->getHandler('Readmes');
289
        $logsHandler = $helper->getHandler('Logs');
290
291
        $logsHandler->updateTableLogs(Constants::LOG_TYPE_UPDATE_START, '', 'OK');
292
        $crDirectories = new \CriteriaCompo();
293
        if ('' !== $dirName) {
294
            $crDirectories->add(new \Criteria('dir_name', $dirName));
295
        } else {
296
            $crDirectories->add(new \Criteria('dir_autoupdate', 1));
297
        }
298
        $crDirectories->add(new \Criteria('dir_online', 1));
299
        $directoriesAll = $directoriesHandler->getAll($crDirectories);
300
        // Get All Directories
301
        $directories = [];
302
        foreach (\array_keys($directoriesAll) as $i) {
303
            $directories[$i] = $directoriesAll[$i]->getValuesDirectories();
304
            $dirName = $directoriesAll[$i]->getVar('dir_name');
305
            $dirContent = $directoriesAll[$i]->getVar('dir_content');
306
            $repos = [];
307
            for ($j = 1; $j <= 9; $j++) {
308
                $repos[$j] = [];
309
                if (Constants::DIRECTORY_TYPE_ORG == $directoriesAll[$i]->getVar('dir_type')) {
310
                    $repos = $this->getOrgRepositories($dirName, 100, $j);
311
                } else {
312
                    $repos = $this->getUserRepositories($dirName, 100, $j);
313
                }
314
                if (false === $repos) {
315
                    return false;
316
                    break 1;
317
                }
318
                if (\count($repos) > 0) {
319
                    $repositoriesHandler->updateTableRepositories($dirName, $repos, true, $dirContent);
320
                } else {
321
                    break 1;
322
                }
323
                if (\count($repos) < 100) {
324
                    break 1;
325
                }
326
            }
327
        }
328
        unset($directories);
329
330
        $releasesHandler->updateRepoReleases();
331
        $readmesHandler->updateRepoReadme();
332
333
        $logsHandler->updateTableLogs(Constants::LOG_TYPE_UPDATE_END, '', 'OK');
334
335
        return true;
336
    }
337
338
    /**
339
     * Get primary setting
340
     *
341
     * @return bool|array
342
     */
343
    private function getSetting()
344
    {
345
        $settingsHandler = $this->helper->getHandler('Settings');
346
        $setting = $settingsHandler->getPrimarySetting();
347
348
        if (0 == \count($setting)) {
349
            \redirect_header(\XOOPS_URL . '/index.php', 3, \_AM_WGGITHUB_THEREARENT_SETTINGS);
0 ignored issues
show
The function redirect_header was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

349
            /** @scrutinizer ignore-call */ \redirect_header(\XOOPS_URL . '/index.php', 3, \_AM_WGGITHUB_THEREARENT_SETTINGS);
Loading history...
350
        }
351
        //$this->userAuth = $setting['user'];
352
        $this->tokenAuth = $setting['token'];
353
354
        return true;
355
    }
356
}
357