GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Restful   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 279
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 98
c 1
b 0
f 0
dl 0
loc 279
rs 10
wmc 29

4 Methods

Rating   Name   Duplication   Size   Complexity  
A index() 0 3 1
F __construct() 0 68 13
A sendError() 0 17 5
B sendPayload() 0 64 10
1
<?php
2
/**
3
 * This file is part of the O2System PHP Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Reactor\Http\Controllers;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Cache\Item;
19
use O2System\Reactor\Http\Controller;
20
use O2System\Psr\Http\Header\ResponseFieldInterface;
21
22
/**
23
 * Class Restful
24
 *
25
 * @package O2System\Reactor\Http\Controllers
26
 */
27
class Restful extends Controller
28
{
29
    /**
30
     * Push headers flag
31
     *
32
     * Used for push default headers by controller.
33
     * Set to FALSE if you want to set default headers on the web-server configuration.
34
     *
35
     * APACHE via .htaccess
36
     * IIS via .webconfig
37
     * Nginx via config
38
     *
39
     * @type string
40
     */
41
    protected $pushDefaultHeaders = false;
42
43
    /**
44
     * Access-Control-Allow-Origin
45
     *
46
     * Used for indicates whether a resource can be shared based by
47
     * returning the value of the Origin request header, "*", or "null" in the response.
48
     *
49
     * @type string
50
     */
51
    protected $accessControlAllowOrigin = '*';
52
53
    /**
54
     * Access-Control-Allow-Credentials
55
     *
56
     * Used for indicates whether the response to request can be exposed when the omit credentials flag is unset.
57
     * When part of the response to a preflight request it indicates that the actual request can include user
58
     * credentials.
59
     *
60
     * @type bool
61
     */
62
    protected $accessControlAllowCredentials = true;
63
64
    /**
65
     * Access-Control-Allow-Methods
66
     *
67
     * Used for indicates, as part of the response to a preflight request,
68
     * which methods can be used during the actual request.
69
     *
70
     * @type array
71
     */
72
    protected $accessControlAllowMethods = [
73
        'GET', // common request
74
        'POST', // used for create, update request
75
        //'PUT', // used for upload files request
76
        //'DELETE', // used for delete request
77
        'OPTIONS', // used for preflight request
78
    ];
79
80
    /**
81
     * Access-Control-Allow-Headers
82
     *
83
     * Used for indicates, as part of the response to a preflight request,
84
     * which header field names can be used during the actual request.
85
     *
86
     * @type int
87
     */
88
    protected $accessControlAllowHeaders = [
89
        'Origin',
90
        'Access-Control-Request-Method',
91
        'Access-Control-Request-Headers',
92
        'X-Api-Authenticate', // API-Authenticate: api_key="xxx", api_secret="xxx", api_signature="xxx"
93
        'X-Api-Token',
94
        'X-Web-Token', // X-Web-Token: xxx (json-web-token)
95
        'X-Csrf-Token',
96
        'X-Xss-Token',
97
        'X-Request-ID',
98
        'X-Requested-With',
99
        'X-Requested-Result',
100
    ];
101
102
    /**
103
     * Access-Control-Allow-Headers
104
     *
105
     * Used for indicates, as part of the response to a preflight request,
106
     * which header field names can be used during the actual request.
107
     *
108
     * @type array
109
     */
110
    protected $accessControlAllowContentTypes = [
111
        'text/html',
112
        'application/json',
113
        'application/xml',
114
    ];
115
116
    /**
117
     * Access-Control-Max-Age
118
     *
119
     * Used for indicates how long the results of a preflight request can be cached in a preflight result cache
120
     *
121
     * @type int
122
     */
123
    protected $accessControlMaxAge = 86400;
124
125
    // ------------------------------------------------------------------------
126
127
    protected $ajaxOnly = false;
128
129
    /**
130
     * Restful::__construct
131
     */
132
    public function __construct()
133
    {
134
        if (is_ajax()) {
135
            output()->setContentType('application/json');
0 ignored issues
show
Bug introduced by
The method setContentType() does not exist on O2System\Kernel\Cli\Output. ( Ignorable by Annotation )

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

135
            output()->/** @scrutinizer ignore-call */ setContentType('application/json');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
136
        } elseif ($this->ajaxOnly === false) {
137
            output()->setContentType('application/json');
138
        } else {
139
            output()->setContentType('text/html');
140
        }
141
142
        if ($contentType = input()->server('HTTP_X_REQUESTED_CONTENT_TYPE')) {
143
            if (in_array($contentType, $this->accessControlAllowContentTypes)) {
144
                output()->setContentType($contentType);
145
            }
146
        }
147
148
        if ($this->pushDefaultHeaders) {
149
150
            $origin = input()->server('HTTP_ORIGIN');
151
152
            /**
153
             * Prepare for preflight modern browser request
154
             *
155
             * Since some server cannot use 'Access-Control-Allow-Origin: *'
156
             * the Access-Control-Allow-Origin will be defined based on requested origin
157
             */
158
            if ($this->accessControlAllowOrigin === '*') {
159
                output()->addHeader(ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_ORIGIN, $origin);
0 ignored issues
show
Bug introduced by
The method addHeader() does not exist on O2System\Kernel\Cli\Output. ( Ignorable by Annotation )

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

159
                output()->/** @scrutinizer ignore-call */ addHeader(ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_ORIGIN, $origin);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
160
            }
161
162
            // Set response access control allowed credentials
163
            if ($this->accessControlAllowCredentials === false) {
164
                output()->addHeader(ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_CREDENTIALS, 'false');
165
            }
166
167
            // Set response access control allowed methods header
168
            if (count($this->accessControlAllowMethods)) {
169
                output()->addHeader(
170
                    ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_METHODS,
171
                    implode(', ', $this->accessControlAllowMethods)
172
                );
173
            }
174
175
            // Set response access control allowed headers header
176
            if (count($this->accessControlAllowHeaders)) {
0 ignored issues
show
Bug introduced by
$this->accessControlAllowHeaders of type integer is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

176
            if (count(/** @scrutinizer ignore-type */ $this->accessControlAllowHeaders)) {
Loading history...
177
                output()->addHeader(
178
                    ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_HEADERS,
179
                    implode(', ', $this->accessControlAllowHeaders)
0 ignored issues
show
Bug introduced by
$this->accessControlAllowHeaders of type integer is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

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

179
                    implode(', ', /** @scrutinizer ignore-type */ $this->accessControlAllowHeaders)
Loading history...
180
                );
181
            }
182
183
            // Set response access control allowed content types header
184
            if (count($this->accessControlAllowContentTypes)) {
185
                output()->addHeader(
186
                    ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_ALLOW_CONTENT_TYPES,
187
                    implode(', ', $this->accessControlAllowContentTypes)
188
                );
189
            }
190
191
            // Set response access control max age header
192
            if ($this->accessControlMaxAge > 0) {
193
                output()->addHeader(ResponseFieldInterface::RESPONSE_ACCESS_CONTROL_MAX_AGE,
194
                    $this->accessControlMaxAge);
195
            }
196
        }
197
198
        if (input()->server('REQUEST_METHOD') === 'OPTIONS') {
199
            exit(EXIT_SUCCESS);
0 ignored issues
show
Best Practice introduced by
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...
200
        }
201
    }
202
203
    // ------------------------------------------------------------------------
204
205
    /**
206
     * Restful::index
207
     */
208
    public function index()
209
    {
210
        output()->sendError(204);
211
    }
212
213
    // ------------------------------------------------------------------------
214
215
    public function sendError($code, $message = null)
216
    {
217
        if ($this->ajaxOnly === false) {
218
            output()->setContentType('application/json');
219
        }
220
221
        if (is_array($code)) {
222
            if (is_numeric(key($code))) {
223
                $message = reset($code);
224
                $code = key($code);
225
            } elseif (isset($code[ 'code' ])) {
226
                $code = $code[ 'code' ];
227
                $message = $code[ 'message' ];
228
            }
229
        }
230
231
        output()->sendError($code, $message);
232
    }
233
234
    // ------------------------------------------------------------------------
235
236
    /**
237
     * Restful::sendPayload
238
     *
239
     * @param mixed $data        The payload data to-be send.
240
     * @param bool  $longPooling Long pooling flag mode.
241
     */
242
    public function sendPayload($data, $longPooling = false)
243
    {
244
        if ($longPooling === false) {
245
            if ($this->ajaxOnly) {
246
                if (is_ajax()) {
247
                    output()->send($data);
0 ignored issues
show
Bug introduced by
The method send() does not exist on O2System\Kernel\Cli\Output. ( Ignorable by Annotation )

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

247
                    output()->/** @scrutinizer ignore-call */ send($data);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
                } else {
249
                    output()->sendError(403);
250
                }
251
            } else {
252
                output()->send($data);
253
            }
254
        } elseif (is_ajax()) {
255
            /**
256
             * Server-side file.
257
             * This file is an infinitive loop. Seriously.
258
             * It gets the cache created timestamp, checks if this is larger than the timestamp of the
259
             * AJAX-submitted timestamp (time of last ajax request), and if so, it sends back a JSON with the data from
260
             * data.txt (and a timestamp). If not, it waits for one seconds and then start the next while step.
261
             *
262
             * Note: This returns a JSON, containing the content of data.txt and the timestamp of the last data.txt change.
263
             * This timestamp is used by the client's JavaScript for the next request, so THIS server-side script here only
264
             * serves new content after the last file change. Sounds weird, but try it out, you'll get into it really fast!
265
             */
266
267
            // set php runtime to unlimited
268
            set_time_limit(0);
269
270
            $longPoolingCacheKey = 'long-pooling-' . session()->get('id');
0 ignored issues
show
Bug introduced by
Are you sure session()->get('id') of type false|mixed 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

270
            $longPoolingCacheKey = 'long-pooling-' . /** @scrutinizer ignore-type */ session()->get('id');
Loading history...
271
            $longPoolingCacheData = null;
272
273
            if ( ! cache()->hasItem($longPoolingCacheKey)) {
274
                cache()->save(new Item($longPoolingCacheKey, $data));
275
            }
276
277
            // main loop
278
            while (true) {
279
                // if ajax request has send a timestamp, then $lastCallTimestamp = timestamp, else $last_call = null
280
                $lastCallTimestamp = (int)input()->getPost('last_call_timestamp');
0 ignored issues
show
Bug introduced by
The method getPost() does not exist on O2System\Kernel\Cli\Input. ( Ignorable by Annotation )

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

280
                $lastCallTimestamp = (int)input()->/** @scrutinizer ignore-call */ getPost('last_call_timestamp');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
281
282
                // PHP caches file data, like requesting the size of a file, by default. clearstatcache() clears that cache
283
                clearstatcache();
284
285
                if (cache()->hasItem($longPoolingCacheKey)) {
286
                    $longPoolingCacheData = cache()->getItem($longPoolingCacheKey);
287
                }
288
289
                // get timestamp of when file has been changed the last time
290
                $longPoolingCacheMetadata = $longPoolingCacheData->getMetadata();
291
292
                // if no timestamp delivered via ajax or data.txt has been changed SINCE last ajax timestamp
293
                if ($lastCallTimestamp == null || $longPoolingCacheMetadata[ 'ctime' ] > $lastCallTimestamp) {
294
                    output()->send([
295
                        'timestamp' => $longPoolingCacheMetadata,
296
                        'data'      => $data,
297
                    ]);
298
                } else {
299
                    // wait for 1 sec (not very sexy as this blocks the PHP/Apache process, but that's how it goes)
300
                    sleep(1);
301
                    continue;
302
                }
303
            }
304
        } else {
305
            output()->sendError(501);
306
        }
307
    }
308
}