AdaptiveFilter::beforeAction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 5
cts 5
cp 1
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * @link https://github.com/vuongxuongminh/yii2-mobile-first
4
 * @copyright Copyright (c) 2019 Vuong Xuong Minh
5
 * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
6
 */
7
8
namespace vxm\mobileFirst;
9
10
use yii\base\ActionFilter;
11
use yii\base\InvalidConfigException;
12
use yii\di\Instance;
13
use yii\web\Request;
14
use yii\web\Response;
15
16
/**
17
 * Class AdaptiveBehavior useful to redirect user to adaptive url.
18
 *
19
 * @author Vuong Minh <[email protected]>
20
 * @since 1.0.0
21
 */
22
class AdaptiveFilter extends ActionFilter
23
{
24
25
    use DetectorTrait;
26
27
    /**
28
     * @var array list of request methods, which should allow page redirection in case wrong protocol is used.
29
     * For all not listed request methods `BadRequestHttpException` will be thrown for secure action, while
30
     * not secure ones will be allowed to be performed via secured protocol.
31
     */
32
    public $redirectRequestMethods = ['GET', 'OPTIONS'];
33
34
    /**
35
     * @var integer the HTTP status code, which should be used in redirection.
36
     */
37
    public $redirectStatusCode = 301;
38
39
    /**
40
     * @var array|string adaptive redirect url it can be an array like ['https://m.yourdomain.com', 'refer' => 'yourdomain.com']
41
     * or https://m.yourdomain.com/&refer=yourdomain.com
42
     */
43
    public $redirectUrl;
44
45
    /**
46
     * @var bool weather you want to keep url requested path.
47
     */
48
    public $keepUrlPath = false;
49
50
    /**
51
     * @var array|string|Request a [[Request]] component id or config of it using for prepare redirect url and checking should be redirect an user to adaptive url.
52
     */
53
    public $request = 'request';
54
55
    /**
56
     * @var array|string|Response a [[Response]] component id or config of it using for redirect an user.
57
     */
58
    public $response = 'response';
59
60
    /**
61
     * @inheritDoc
62
     * @throws \yii\base\InvalidConfigException
63
     */
64 8
    public function init()
65
    {
66 8
        $this->request = Instance::ensure($this->request, Request::class);
67 8
        $this->response = Instance::ensure($this->response, Response::class);
68
69 8
        parent::init();
70 8
    }
71
72
    /**
73
     * @inheritDoc
74
     * @throws InvalidConfigException
75
     */
76 4
    public function beforeAction($action)
77
    {
78 4
        if ($this->shouldRedirect()) {
79
80 2
            $this->response->redirect($this->getRedirectUrl(), $this->redirectStatusCode);
81
82 2
            return false;
83
        } else {
84
85 2
            return true;
86
        }
87
    }
88
89
    /**
90
     * Get a adaptive redirect url
91
     *
92
     * @return string url
93
     * @throws InvalidConfigException
94
     */
95 4
    protected function getRedirectUrl(): string
96
    {
97 4
        if ($this->redirectUrl === null) {
98
99 1
            throw new InvalidConfigException('Property `redirectUrl` must be set!');
100 3
        } elseif (is_string($this->redirectUrl)) {
101
102 3
            $url = $this->redirectUrl;
103 3
            $params = [];
104
        } else {
105
106
            $params = $this->redirectUrl;
107
            $url = array_unshift($params);
108
        }
109
110 3
        if ($this->keepUrlPath) {
111
112
            $url = rtrim($url, '/') . '/' . ltrim($this->request->getUrl());
113
        }
114
115 3
        $params = http_build_query($params, '', '&');
116
117 3
        if (strpos($url, '?') !== false) {
118
            $paramSeparator = '&';
119
        } else {
120 3
            $paramSeparator = '?';
121
        }
122
123 3
        return $url . $paramSeparator . $params;
124
    }
125
126
    /**
127
     * Method checking should redirect to adaptive url or not.
128
     *
129
     * @return boolean whether current web request method is considered as 'read' type.
130
     * @throws InvalidConfigException
131
     */
132 4
    protected function shouldRedirect(): bool
133
    {
134 4
        $isMobile = $this->getDetector()->isMobile();
135 4
        $isRedirectRequestMethod = in_array($this->request->getMethod(), $this->redirectRequestMethods, true);
136 4
        $hostName = $this->request->getHostName();
137 4
        $redirectHostName = parse_url($this->getRedirectUrl(), PHP_URL_HOST);
138
139 3
        return strcasecmp($hostName, $redirectHostName) !== 0 && $isMobile && $isRedirectRequestMethod;
140
    }
141
142
143
}
144