Issues   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 59
c 2
b 0
f 1
dl 0
loc 235
rs 10
wmc 21

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getHdrSize() 0 3 1
A __construct() 0 11 1
A setError() 0 3 1
A getCachedEtag() 0 3 2
A handleHeaderLine() 0 5 1
A getSessPrefix() 0 3 1
A getHeaderFromArray() 0 11 4
A getServiceUrl() 0 3 1
A getsKeyHdrSize() 0 3 1
A getsKeyEtag() 0 3 1
A execCurl() 0 34 1
A getCurlResponse() 0 3 2
A getsKeyResponse() 0 3 1
A getError() 0 3 1
A setSessPrefix() 0 5 1
A getsKeyArray() 0 3 1
1
<?php declare(strict_types=1);
2
3
//declare(strict_types=1); //mb do not use it here, as it generates conflict on line 280: base64_encode(): Argument #1 ($string) must be of type string, bool given
4
5
namespace XoopsModules\Tag;
6
7
/*
8
 You may not change or alter any portion of this comment or credits of
9
 supporting developers from this source code or any supporting source code
10
 which is considered copyrighted (c) material of the original comment or credit
11
 authors.
12
13
 This program is distributed in the hope that it will be useful, but
14
 WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
 */
17
/**
18
 * Module: Tag
19
 *
20
 * @author    ZySpec <[email protected]>
21
 * @copyright Copyright (c) 2001-2019 {@link https://xoops.org XOOPS Project}}
22
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GNU Public License
23
 * @since     2.00
24
 */
25
26
/**
27
 * Issues class to collect information from GitHub
28
 */
29
class Issues
30
{
31
    /**
32
     * @var array
33
     */
34
    protected $hdrs;
35
    /**
36
     * @var string module directory name
37
     */
38
    protected $dirname;
39
    /**
40
     * @var string response from involking curl
41
     */
42
    protected $curl_response;
43
    /**
44
     * @var int Curl response header size
45
     */
46
    protected $hdrSize;
47
    /**
48
     * @var string Service URL for curl
49
     */
50
    protected $serviceUrl;
51
    /**
52
     * @var string prefix for all SESSION vars
53
     */
54
    protected $sessPrefix;
55
    /**
56
     * @var string class error text
57
     */
58
    protected $err;
59
60
    /**
61
     * Constructor
62
     *
63
     * return void
64
     */
65
    public function __construct()
66
    {
67
        $this->hdrs          = [];
68
        $this->curl_response = '';
69
        $this->hdrSize       = 0;
70
        $this->dirname       = \basename(\dirname(__DIR__));
71
        //$this->serviceUrl    = 'https://api.github.com/repos/xoops/xoopscore25/issues?state=open';
72
        //$this->serviceUrl    = 'https://github.com/zyspec/' . $this->dirname . '/issues?state=open';
73
        $this->serviceUrl = 'https://api.github.com/repos/XoopsModules25x/' . $this->dirname . '/issues?state=open';
74
        $this->setSessPrefix($this->dirname);
75
        $this->err = '';
76
    }
77
78
    /**
79
     * Function to put HTTP headers in an array
80
     *
81
     * @param resource $curl
82
     *
83
     * @return int length of header line put into array
84
     */
85
    public function handleHeaderLine($curl, string $hdrLine): int
86
    {
87
        $this->hdrs[] = \trim($hdrLine);
88
89
        return mb_strlen($hdrLine);
90
    }
91
92
    /**
93
     * Function to get a header from the header array
94
     *
95
     *
96
     * @return array|string array($hdr => value) or false if not found
97
     */
98
    public function getHeaderFromArray(string $hdr, bool $asArray = false)
99
    {
100
        $val = '';
101
        foreach ($this->hdrs as $thisHdr) {
102
            if (\preg_match("/^{$hdr}/i", $thisHdr)) {
103
                $val = mb_substr($thisHdr, mb_strlen($hdr));
104
                break;
105
            }
106
        }
107
108
        return $asArray ? [$hdr => \trim($val)] : \trim($val);
109
    }
110
111
    /**
112
     * Returns response from involking Curl
113
     *
114
     * @param bool $serialized (default = false)
115
     */
116
    public function getCurlResponse(bool $serialized = false): string
117
    {
118
        return $serialized ? \serialize(\base64_encode($this->curl_response)) : $this->curl_response;
119
    }
120
121
    /**
122
     * Get the size of curl response headers
123
     *
124
     * @return int size of header in bytes
125
     */
126
    public function getHdrSize(): int
127
    {
128
        return $this->hdrSize;
129
    }
130
131
    /**
132
     * Get the URL for curl
133
     */
134
    public function getServiceUrl(): string
135
    {
136
        return $this->serviceUrl;
137
    }
138
139
    /**
140
     * Get the Prefix for SESSION variable
141
     */
142
    public function getSessPrefix(): string
143
    {
144
        return $this->sessPrefix;
145
    }
146
147
    /**
148
     * Set the Prefix for SESSION variable
149
     *
150
     * @param string $prefix string to prepend to session variable
151
     *
152
     * @return string prefix
153
     */
154
    public function setSessPrefix(string $prefix): string
155
    {
156
        $this->sessPrefix = \htmlspecialchars($prefix, \ENT_QUOTES | \ENT_HTML5) . '_';
157
158
        return $this->sessPrefix;
159
    }
160
161
    /**
162
     * Get the SESSION variable name for Etag key
163
     */
164
    public function getsKeyEtag(): string
165
    {
166
        return $this->sessPrefix . 'github_etag';
167
    }
168
169
    /**
170
     * Get the SESSION variable name for Header Size key
171
     */
172
    public function getsKeyHdrSize(): string
173
    {
174
        return $this->sessPrefix . 'github_hdr_size';
175
    }
176
177
    /**
178
     * Get the SESSION variable name for Response key
179
     */
180
    public function getsKeyResponse(): string
181
    {
182
        return $this->sessPrefix . 'github_curl_response';
183
    }
184
185
    /**
186
     * Get the SESSION variable name for Array key
187
     */
188
    public function getsKeyArray(): array
189
    {
190
        return [$this->getsKeyEtag(), $this->getsKeyHdrSize(), $this->getsKeyResponse()];
191
    }
192
193
    /**
194
     * Get the SESSION cached Etag key contents
195
     *
196
     * @return string|bool Etag key or false if tag not set
197
     */
198
    public function getCachedEtag()
199
    {
200
        return isset($_SESSION[$this->getsKeyEtag()]) ? \base64_decode(\unserialize($_SESSION[$this->getsKeyEtag()]), true) : false;
201
    }
202
203
    /**
204
     * Set the error message associated with the latest Curl operation
205
     *
206
     * @param string $msg the error message to save
207
     */
208
    public function setError(string $msg): void
209
    {
210
        $this->err = $msg;
211
    }
212
213
    /**
214
     * Get the error message associated with the latest Curl operation
215
     *
216
     * @return string the current error message
217
     */
218
    public function getError(): string
219
    {
220
        return $this->err;
221
    }
222
223
    /**
224
     * Execute a curl operation to retrieve data from GitHub server
225
     *
226
     * Also sets the SESSION vars for the curl operation
227
     *
228
     * @return int the current header size from curl
229
     */
230
    public function execCurl(): int
231
    {
232
        $curl = \curl_init($this->getServiceUrl());
233
        \curl_setopt_array(
234
            $curl,
235
            [
236
                \CURLOPT_RETURNTRANSFER => true,
237
                \CURLOPT_HEADER         => true,
238
                \CURLOPT_VERBOSE        => true,
239
                \CURLOPT_TIMEOUT        => 5,
240
                \CURLOPT_HTTPGET        => true,
241
                \CURLOPT_USERAGENT      => 'XOOPS-' . \mb_strtoupper($this->dirname),
242
                \CURLOPT_HTTPHEADER     => [
243
                    'Content-type:application/json',
244
                    'If-None-Match: ' . $this->getCachedEtag(),
0 ignored issues
show
Bug introduced by
Are you sure $this->getCachedEtag() of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

244
                    'If-None-Match: ' . /** @scrutinizer ignore-type */ $this->getCachedEtag(),
Loading history...
245
                ],
246
                \CURLINFO_HEADER_OUT    => true,
247
                \CURLOPT_HEADERFUNCTION => [$this, 'handleHeaderLine'],
248
            ]
249
        );
250
        // execute the session
251
        $this->curl_response = \curl_exec($curl);
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_exec($curl) can also be of type true. However, the property $curl_response is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
252
        // get the header size and finish off the session
253
        $this->hdrSize = \curl_getinfo($curl, \CURLINFO_HEADER_SIZE);
254
        $this->hdrSize = (int)$this->hdrSize;
255
        \curl_close($curl);
256
257
        $hdrEtag = $this->getHeaderFromArray('Etag: ');
258
259
        $_SESSION[$this->getsKeyEtag()]     = \serialize(\base64_encode($hdrEtag));
260
        $_SESSION[$this->getsKeyHdrSize()]  = \serialize($this->hdrSize);
261
        $_SESSION[$this->getsKeyResponse()] = \serialize(\base64_encode($this->curl_response));
0 ignored issues
show
Bug introduced by
It seems like $this->curl_response can also be of type true; however, parameter $string of base64_encode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

261
        $_SESSION[$this->getsKeyResponse()] = \serialize(\base64_encode(/** @scrutinizer ignore-type */ $this->curl_response));
Loading history...
262
263
        return $this->hdrSize;
264
    }
265
}
266