Completed
Branch BUG/fix-wordpress-heartbeat (c66ef1)
by
unknown
09:48 queued 34s
created

Request   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 606
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 606
rs 2.634
c 0
b 0
f 0
wmc 72
lcom 4
cbo 1

40 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A setRequestTypeContextChecker() 0 4 1
A getParams() 0 4 1
A postParams() 0 4 1
A cookieParams() 0 4 1
A serverParams() 0 4 1
A requestParams() 0 4 1
B setRequestParam() 0 10 7
A getRequestParam() 0 4 1
A requestParamIsSet() 0 4 1
A getMatch() 0 4 1
A matches() 0 4 1
B match() 0 24 7
B requestParameterDrillDown() 0 48 11
A unSetRequestParam() 0 7 2
A ipAddress() 0 4 1
B visitorIp() 0 23 6
A requestUri() 0 14 2
A userAgent() 0 4 1
A setUserAgent() 0 7 4
A isBot() 0 4 1
A setIsBot() 0 4 1
A isActivation() 0 4 1
A setIsActivation() 0 4 1
A isAdmin() 0 4 1
A isAdminAjax() 0 4 1
A isAjax() 0 4 1
A isEeAjax() 0 4 1
A isOtherAjax() 0 4 1
A isApi() 0 4 1
A isCli() 0 4 1
A isCron() 0 4 1
A isFeed() 0 4 1
A isFrontend() 0 4 1
A isFrontAjax() 0 4 1
A isIframe() 0 4 1
A isWordPressApi() 0 4 1
A isWordPressHeartbeat() 0 4 1
A isWordPressScrape() 0 4 1
A slug() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Request often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Request, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace EventEspresso\core\services\request;
4
5
use EventEspresso\core\domain\services\contexts\RequestTypeContextCheckerInterface;
6
use EventEspresso\core\interfaces\InterminableInterface;
7
use EventEspresso\core\interfaces\ReservedInstanceInterface;
8
9
/**
10
 * Class Request
11
 * Representation of an incoming, server-side HTTP request
12
 *
13
 * @package EventEspresso\core\services\request
14
 * @author  Brent Christensen
15
 * @since   4.9.53
16
 */
17
class Request implements InterminableInterface, RequestInterface, ReservedInstanceInterface
18
{
19
20
    /**
21
     * $_GET parameters
22
     *
23
     * @var array $get
24
     */
25
    private $get;
26
27
    /**
28
     * $_POST parameters
29
     *
30
     * @var array $post
31
     */
32
    private $post;
33
34
    /**
35
     * $_COOKIE parameters
36
     *
37
     * @var array $cookie
38
     */
39
    private $cookie;
40
41
    /**
42
     * $_SERVER parameters
43
     *
44
     * @var array $server
45
     */
46
    private $server;
47
48
    /**
49
     * $_REQUEST parameters
50
     *
51
     * @var array $request
52
     */
53
    private $request;
54
55
    /**
56
     * @var RequestTypeContextCheckerInterface
57
     */
58
    private $request_type;
59
60
    /**
61
     * IP address for request
62
     *
63
     * @var string $ip_address
64
     */
65
    private $ip_address;
66
67
    /**
68
     * @var string $user_agent
69
     */
70
    private $user_agent;
71
72
    /**
73
     * true if current user appears to be some kind of bot
74
     *
75
     * @var bool $is_bot
76
     */
77
    private $is_bot;
78
79
80
    /**
81
     * @param array $get
82
     * @param array $post
83
     * @param array $cookie
84
     * @param array $server
85
     */
86
    public function __construct(array $get, array $post, array $cookie, array $server)
87
    {
88
        // grab request vars
89
        $this->get = $get;
90
        $this->post = $post;
91
        $this->cookie = $cookie;
92
        $this->server = $server;
93
        $this->request = array_merge($this->get, $this->post);
94
        $this->ip_address = $this->visitorIp();
95
    }
96
97
98
    /**
99
     * @param RequestTypeContextCheckerInterface $type
100
     */
101
    public function setRequestTypeContextChecker(RequestTypeContextCheckerInterface $type)
102
    {
103
        $this->request_type = $type;
104
    }
105
106
107
    /**
108
     * @return array
109
     */
110
    public function getParams()
111
    {
112
        return $this->get;
113
    }
114
115
116
    /**
117
     * @return array
118
     */
119
    public function postParams()
120
    {
121
        return $this->post;
122
    }
123
124
125
    /**
126
     * @return array
127
     */
128
    public function cookieParams()
129
    {
130
        return $this->cookie;
131
    }
132
133
134
    /**
135
     * @return array
136
     */
137
    public function serverParams()
138
    {
139
        return $this->server;
140
    }
141
142
143
    /**
144
     * returns contents of $_REQUEST
145
     *
146
     * @return array
147
     */
148
    public function requestParams()
149
    {
150
        return $this->request;
151
    }
152
153
154
    /**
155
     * @param      $key
156
     * @param      $value
157
     * @param bool $override_ee
158
     * @return    void
159
     */
160
    public function setRequestParam($key, $value, $override_ee = false)
161
    {
162
        // don't allow "ee" to be overwritten unless explicitly instructed to do so
163
        if ($key !== 'ee'
164
            || ($key === 'ee' && empty($this->request['ee']))
165
            || ($key === 'ee' && ! empty($this->request['ee']) && $override_ee)
166
        ) {
167
            $this->request[ $key ] = $value;
168
        }
169
    }
170
171
172
    /**
173
     * returns   the value for a request param if the given key exists
174
     *
175
     * @param       $key
176
     * @param null  $default
177
     * @return mixed
178
     */
179
    public function getRequestParam($key, $default = null)
180
    {
181
        return $this->requestParameterDrillDown($key, $default, 'get');
182
    }
183
184
185
    /**
186
     * check if param exists
187
     *
188
     * @param       $key
189
     * @return bool
190
     */
191
    public function requestParamIsSet($key)
192
    {
193
        return $this->requestParameterDrillDown($key);
194
    }
195
196
197
    /**
198
     * check if a request parameter exists whose key that matches the supplied wildcard pattern
199
     * and return the value for the first match found
200
     * wildcards can be either of the following:
201
     *      ? to represent a single character of any type
202
     *      * to represent one or more characters of any type
203
     *
204
     * @param string     $pattern
205
     * @param null|mixed $default
206
     * @return mixed
207
     */
208
    public function getMatch($pattern, $default = null)
209
    {
210
        return $this->requestParameterDrillDown($pattern, $default, 'match');
211
    }
212
213
214
    /**
215
     * check if a request parameter exists whose key matches the supplied wildcard pattern
216
     * wildcards can be either of the following:
217
     *      ? to represent a single character of any type
218
     *      * to represent one or more characters of any type
219
     * returns true if a match is found or false if not
220
     *
221
     * @param string $pattern
222
     * @return bool
223
     */
224
    public function matches($pattern)
225
    {
226
        return $this->requestParameterDrillDown($pattern, null, 'match') !== null;
227
    }
228
229
230
    /**
231
     * @see https://stackoverflow.com/questions/6163055/php-string-matching-with-wildcard
232
     * @param string $pattern               A string including wildcards to be converted to a regex pattern
233
     *                                      and used to search through the current request's parameter keys
234
     * @param array  $request_params        The array of request parameters to search through
235
     * @param mixed  $default               [optional] The value to be returned if no match is found.
236
     *                                      Default is null
237
     * @param string $return                [optional] Controls what kind of value is returned.
238
     *                                      Options are:
239
     *                                      'bool' will return true or false if match is found or not
240
     *                                      'key' will return the first key found that matches the supplied pattern
241
     *                                      'value' will return the value for the first request parameter
242
     *                                      whose key matches the supplied pattern
243
     *                                      Default is 'value'
244
     * @return boolean|string
245
     */
246
    private function match($pattern, array $request_params, $default = null, $return = 'value')
247
    {
248
        $return = in_array($return, array('bool', 'key', 'value'), true)
249
            ? $return
250
            : 'is_set';
251
        // replace wildcard chars with regex chars
252
        $pattern = str_replace(
253
            array("\*", "\?"),
254
            array('.*', '.'),
255
            preg_quote($pattern, '/')
256
        );
257
        foreach ($request_params as $key => $request_param) {
258
            if (preg_match('/^' . $pattern . '$/is', $key)) {
259
                // return value for request param
260
                if ($return === 'value') {
261
                    return $request_params[ $key ];
262
                }
263
                // or actual key or true just to indicate it was found
264
                return $return === 'key' ? $key : true;
265
            }
266
        }
267
        // match not found so return default value or false
268
        return $return === 'value' ? $default : false;
269
    }
270
271
272
    /**
273
     * the supplied key can be a simple string to represent a "top-level" request parameter
274
     * or represent a key for a request parameter that is nested deeper within the request parameter array,
275
     * by using square brackets to surround keys for deeper array elements.
276
     * For example :
277
     * if the supplied $key was: "first[second][third]"
278
     * then this will attempt to drill down into the request parameter array to find a value.
279
     * Given the following request parameters:
280
     *  array(
281
     *      'first' => array(
282
     *          'second' => array(
283
     *              'third' => 'has a value'
284
     *          )
285
     *      )
286
     *  )
287
     * would return true if default parameters were set
288
     *
289
     * @param string $callback
290
     * @param        $key
291
     * @param null   $default
292
     * @param array  $request_params
293
     * @return bool|mixed|null
294
     */
295
    private function requestParameterDrillDown(
296
        $key,
297
        $default = null,
298
        $callback = 'is_set',
299
        array $request_params = array()
300
    ) {
301
        $callback = in_array($callback, array('is_set', 'get', 'match'), true)
302
            ? $callback
303
            : 'is_set';
304
        $request_params = ! empty($request_params)
305
            ? $request_params
306
            : $this->request;
307
        // does incoming key represent an array like 'first[second][third]'  ?
308
        if (strpos($key, '[') !== false) {
309
            // turn it into an actual array
310
            $key = str_replace(']', '', $key);
311
            $keys = explode('[', $key);
312
            $key = array_shift($keys);
313
            if ($callback === 'match') {
314
                $real_key = $this->match($key, $request_params, $default, 'key');
315
                $key = $real_key ? $real_key : $key;
316
            }
317
            // check if top level key exists
318
            if (isset($request_params[ $key ])) {
319
                // build a new key to pass along like: 'second[third]'
320
                // or just 'second' depending on depth of keys
321
                $key_string = array_shift($keys);
322
                if (! empty($keys)) {
323
                    $key_string .= '[' . implode('][', $keys) . ']';
324
                }
325
                return $this->requestParameterDrillDown(
326
                    $key_string,
327
                    $default,
328
                    $callback,
329
                    $request_params[ $key ]
330
                );
331
            }
332
        }
333
        if ($callback === 'is_set') {
334
            return isset($request_params[ $key ]);
335
        }
336
        if ($callback === 'match') {
337
            return $this->match($key, $request_params, $default);
338
        }
339
        return isset($request_params[ $key ])
340
            ? $request_params[ $key ]
341
            : $default;
342
    }
343
344
345
    /**
346
     * remove param
347
     *
348
     * @param      $key
349
     * @param bool $unset_from_global_too
350
     */
351
    public function unSetRequestParam($key, $unset_from_global_too = false)
352
    {
353
        unset($this->request[ $key ]);
354
        if ($unset_from_global_too) {
355
            unset($_REQUEST[ $key ]);
356
        }
357
    }
358
359
360
    /**
361
     * @return string
362
     */
363
    public function ipAddress()
364
    {
365
        return $this->ip_address;
366
    }
367
368
369
    /**
370
     * attempt to get IP address of current visitor from server
371
     * plz see: http://stackoverflow.com/a/2031935/1475279
372
     *
373
     * @access public
374
     * @return string
375
     */
376
    private function visitorIp()
377
    {
378
        $visitor_ip = '0.0.0.0';
379
        $server_keys = array(
380
            'HTTP_CLIENT_IP',
381
            'HTTP_X_FORWARDED_FOR',
382
            'HTTP_X_FORWARDED',
383
            'HTTP_X_CLUSTER_CLIENT_IP',
384
            'HTTP_FORWARDED_FOR',
385
            'HTTP_FORWARDED',
386
            'REMOTE_ADDR',
387
        );
388
        foreach ($server_keys as $key) {
389
            if (isset($this->server[ $key ])) {
390
                foreach (array_map('trim', explode(',', $this->server[ $key ])) as $ip) {
391
                    if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
392
                        $visitor_ip = $ip;
393
                    }
394
                }
395
            }
396
        }
397
        return $visitor_ip;
398
    }
399
400
401
    /**
402
     * @return string
403
     */
404
    public function requestUri()
405
    {
406
        $request_uri = filter_input(
407
            INPUT_SERVER,
408
            'REQUEST_URI',
409
            FILTER_SANITIZE_URL,
410
            FILTER_NULL_ON_FAILURE
411
        );
412
        if (empty($request_uri)) {
413
            // fallback sanitization if the above fails
414
            $request_uri = wp_sanitize_redirect($this->server['REQUEST_URI']);
415
        }
416
        return $request_uri;
417
    }
418
419
420
    /**
421
     * @return string
422
     */
423
    public function userAgent()
424
    {
425
        return $this->user_agent;
426
    }
427
428
429
    /**
430
     * @param string $user_agent
431
     */
432
    public function setUserAgent($user_agent = '')
433
    {
434
        if ($user_agent === '' || ! is_string($user_agent)) {
435
            $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) esc_attr($_SERVER['HTTP_USER_AGENT']) : '';
436
        }
437
        $this->user_agent = $user_agent;
438
    }
439
440
441
    /**
442
     * @return bool
443
     */
444
    public function isBot()
445
    {
446
        return $this->is_bot;
447
    }
448
449
450
    /**
451
     * @param bool $is_bot
452
     */
453
    public function setIsBot($is_bot)
454
    {
455
        $this->is_bot = filter_var($is_bot, FILTER_VALIDATE_BOOLEAN);
456
    }
457
458
459
    /**
460
     * @return bool
461
     */
462
    public function isActivation()
463
    {
464
        return $this->request_type->isActivation();
465
    }
466
467
468
    /**
469
     * @param $is_activation
470
     * @return bool
471
     */
472
    public function setIsActivation($is_activation)
473
    {
474
        return $this->request_type->setIsActivation($is_activation);
475
    }
476
477
478
    /**
479
     * @return bool
480
     */
481
    public function isAdmin()
482
    {
483
        return $this->request_type->isAdmin();
484
    }
485
486
487
    /**
488
     * @return bool
489
     */
490
    public function isAdminAjax()
491
    {
492
        return $this->request_type->isAdminAjax();
493
    }
494
495
496
    /**
497
     * @return bool
498
     */
499
    public function isAjax()
500
    {
501
        return $this->request_type->isAjax();
502
    }
503
504
505
    /**
506
     * @return bool
507
     */
508
    public function isEeAjax()
509
    {
510
        return $this->request_type->isEeAjax();
511
    }
512
513
514
    /**
515
     * @return bool
516
     */
517
    public function isOtherAjax()
518
    {
519
        return $this->request_type->isOtherAjax();
520
    }
521
522
523
    /**
524
     * @return bool
525
     */
526
    public function isApi()
527
    {
528
        return $this->request_type->isApi();
529
    }
530
531
532
    /**
533
     * @return bool
534
     */
535
    public function isCli()
536
    {
537
        return $this->request_type->isCli();
538
    }
539
540
541
    /**
542
     * @return bool
543
     */
544
    public function isCron()
545
    {
546
        return $this->request_type->isCron();
547
    }
548
549
550
    /**
551
     * @return bool
552
     */
553
    public function isFeed()
554
    {
555
        return $this->request_type->isFeed();
556
    }
557
558
559
    /**
560
     * @return bool
561
     */
562
    public function isFrontend()
563
    {
564
        return $this->request_type->isFrontend();
565
    }
566
567
568
    /**
569
     * @return bool
570
     */
571
    public function isFrontAjax()
572
    {
573
        return $this->request_type->isFrontAjax();
574
    }
575
576
577
    /**
578
     * @return bool
579
     */
580
    public function isIframe()
581
    {
582
        return $this->request_type->isIframe();
583
    }
584
585
586
    /**
587
     * @return bool
588
     */
589
    public function isWordPressApi()
590
    {
591
        return $this->request_type->isWordPressApi();
592
    }
593
594
595
596
    /**
597
     * @return bool
598
     */
599
    public function isWordPressHeartbeat()
600
    {
601
        return $this->request_type->isWordPressHeartbeat();
602
    }
603
604
605
606
    /**
607
     * @return bool
608
     */
609
    public function isWordPressScrape()
610
    {
611
        return $this->request_type->isWordPressScrape();
612
    }
613
614
615
    /**
616
     * @return string
617
     */
618
    public function slug()
619
    {
620
        return $this->request_type->slug();
621
    }
622
}
623