Passed
Pull Request — master (#24)
by Michael
04:54 queued 02:40
created

Issues::getCachedEtag()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 1
c 1
b 0
f 1
nc 2
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace XoopsModules\Tag;
4
5
/*
6
 You may not change or alter any portion of this comment or credits of
7
 supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit
9
 authors.
10
11
 This program is distributed in the hope that it will be useful, but
12
 WITHOUT ANY WARRANTY; without even the implied warranty of
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 */
15
/**
16
 * Module: Tag
17
 *
18
 * @package   XoopsModules\Tag
19
 * @author    ZySpec <[email protected]>
20
 * @copyright Copyright (c) 2001-2019 {@link https://xoops.org XOOPS Project}}
21
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GNU Public License
22
 * @since     2.00
23
 */
24
25
/**
26
 * Issues class to collect information from GitHub
27
 *
28
 */
29
class Issues
30
{
31
    /**
32
     * @var array $hdrs
33
     */
34
    protected $hdrs;
35
    /**
36
     * @var string $dirname module directory name
37
     */
38
    protected $dirname;
39
    /**
40
     * @var string $curl_respones response from involking curl
41
     */
42
    protected $curl_response;
43
    /**
44
     * @var int $hdrSize Curl response header size
45
     */
46
    protected $hdrSize;
47
    /**
48
     * @var string $serviceUrl Service URL for curl
49
     */
50
    protected $serviceUrl;
51
    /**
52
     * @var string $sessPrefix prefix for all SESSION vars
53
     */
54
    protected $sessPrefix;
55
    /**
56
     * @var string $err 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        $curl
82
     * @param string $hdrLine
83
     *
84
     * @return int length of header line put into array
85
     */
86
    public function handleHeaderLine($curl, $hdrLine)
87
    {
88
        $this->hdrs[] = \trim($hdrLine);
89
        return \strlen($hdrLine);
90
    }
91
92
    /**
93
     * Function to get a header from the header array
94
     *
95
     * @param string $hdr
96
     * @param bool   $asArray
97
     *
98
     * @return array|string array($hdr => value) or false if not found
99
     */
100
    public function getHeaderFromArray($hdr, $asArray = false)
101
    {
102
        $val = '';
103
        foreach ($this->hdrs as $thisHdr) {
104
            if (\preg_match("/^{$hdr}/i", $thisHdr)) {
105
                $val = \substr($thisHdr, \strlen($hdr));
106
                break;
107
            }
108
        }
109
        return (bool)$asArray ? [$hdr => \trim($val)] : \trim($val);
110
    }
111
112
    /**
113
     * Returns response from involking Curl
114
     *
115
     * @param bool $serialized (default = false)
116
     *
117
     * @return string
118
     */
119
    public function getCurlResponse($serialized = false)
120
    {
121
        return (bool)$serialized ? \serialize(\base64_encode($this->curl_response)) : $this->curl_response;
122
    }
123
124
    /**
125
     * Get the size of curl response headers
126
     *
127
     * @return int size of header in bytes
128
     */
129
    public function getHdrSize()
130
    {
131
        return $this->hdrSize;
132
    }
133
134
    /**
135
     * Get the URL for curl
136
     *
137
     * @return string
138
     */
139
    public function getServiceUrl()
140
    {
141
        return $this->serviceUrl;
142
    }
143
144
    /**
145
     * Get the Prefix for SESSION variable
146
     *
147
     * @return string
148
     */
149
    public function getSessPrefix()
150
    {
151
        return $this->sessPrefix;
152
    }
153
154
    /**
155
     * Set the Prefix for SESSION variable
156
     *
157
     * @param string $prefix string to prepend to session variable
158
     *
159
     * @return string prefix
160
     */
161
    public function setSessPrefix($prefix)
162
    {
163
        $this->sessPrefix = \htmlspecialchars($prefix, \ENT_QUOTES | \ENT_HTML5) . '_';
164
        return $this->sessPrefix;
165
    }
166
167
    /**
168
     * Get the SESSION variable name for Etag key
169
     *
170
     * @return string
171
     */
172
    public function getsKeyEtag()
173
    {
174
        return $this->sessPrefix . 'github_etag';
175
    }
176
177
    /**
178
     * Get the SESSION variable name for Header Size key
179
     *
180
     * @return string
181
     */
182
    public function getsKeyHdrSize()
183
    {
184
        return $this->sessPrefix . 'github_hdr_size';
185
    }
186
187
    /**
188
     * Get the SESSION variable name for Response key
189
     *
190
     * @return string
191
     */
192
    public function getsKeyResponse()
193
    {
194
        return $this->sessPrefix . 'github_curl_response';
195
    }
196
197
    /**
198
     * Get the SESSION variable name for Array key
199
     *
200
     * @return array
201
     */
202
    public function getsKeyArray()
203
    {
204
        return [$this->getsKeyEtag(), $this->getsKeyHdrSize(), $this->getsKeyResponse()];
205
    }
206
207
    /**
208
     * Get the SESSION cached Etag key contents
209
     *
210
     * @return string|bool Etag key or false if tag not set
211
     */
212
    public function getCachedEtag()
213
    {
214
        return isset($_SESSION[$this->getsKeyEtag()]) ? \base64_decode(\unserialize($_SESSION[$this->getsKeyEtag()])) : false;
215
    }
216
217
    /**
218
     * Set the error message associated with the latest Curl operation
219
     *
220
     * @param string $msg the error message to save
221
     *
222
     * @return void
223
     */
224
    public function setError($msg)
225
    {
226
        $this->err = $msg;
227
    }
228
229
    /**
230
     * Get the error message associated with the latest Curl operation
231
     *
232
     * @return string the current error message
233
     */
234
    public function getError()
235
    {
236
        return $this->err;
237
    }
238
239
    /**
240
     * Execute a curl operation to retrieve data from GitHub server
241
     *
242
     * Also sets the SESSION vars for the curl operation
243
     *
244
     * @return int the current header size from curl
245
     */
246
    public function execCurl()
247
    {
248
        $curl = \curl_init($this->getServiceUrl());
249
        \curl_setopt_array(
250
            $curl,
251
            [
252
                \CURLOPT_RETURNTRANSFER => true,
253
                \CURLOPT_HEADER         => true,
254
                \CURLOPT_VERBOSE        => true,
255
                \CURLOPT_TIMEOUT        => 5,
256
                \CURLOPT_HTTPGET        => true,
257
                \CURLOPT_USERAGENT      => 'XOOPS-' . $this->dirname,
258
                \CURLOPT_HTTPHEADER     => [
259
                    'Content-type:application/json',
260
                    '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

260
                    'If-None-Match: ' . /** @scrutinizer ignore-type */ $this->getCachedEtag(),
Loading history...
261
                ],
262
                \CURLINFO_HEADER_OUT    => true,
263
                \CURLOPT_HEADERFUNCTION => [$this, 'handleHeaderLine'],
264
            ]
265
        );
266
        // execute the session
267
        $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...
268
        // get the header size and finish off the session
269
        $this->hdrSize = \curl_getinfo($curl, \CURLINFO_HEADER_SIZE);
270
        $this->hdrSize = (int)$this->hdrSize;
271
        \curl_close($curl);
272
273
        $hdrEtag = $this->getHeaderFromArray('Etag: ');
274
275
        $_SESSION[$this->getsKeyEtag()]     = \serialize(\base64_encode($hdrEtag));
0 ignored issues
show
Bug introduced by
It seems like $hdrEtag can also be of type array<string,string>; 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

275
        $_SESSION[$this->getsKeyEtag()]     = \serialize(\base64_encode(/** @scrutinizer ignore-type */ $hdrEtag));
Loading history...
276
        $_SESSION[$this->getsKeyHdrSize()]  = \serialize($this->hdrSize);
277
        $_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

277
        $_SESSION[$this->getsKeyResponse()] = \serialize(\base64_encode(/** @scrutinizer ignore-type */ $this->curl_response));
Loading history...
278
        return $this->hdrSize;
279
    }
280
}
281