Passed
Push — 2.x ( b3a28e...4bb95a )
by Terry
01:45
created

TemplateTrait::respond()   B

Complexity

Conditions 7
Paths 25

Size

Total Lines 105
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 64
c 1
b 0
f 0
nc 25
nop 0
dl 0
loc 105
rs 7.8521

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 * 
10
 * php version 7.1.0
11
 * 
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <[email protected]>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20
21
declare(strict_types=1);
22
23
namespace Shieldon\Firewall\Kernel;
24
25
use Psr\Http\Message\ResponseInterface;
26
use Shieldon\Firewall\Kernel;
27
use Shieldon\Firewall\HttpFactory;
28
use function Shieldon\Firewall\get_response;
29
use function Shieldon\Firewall\get_request;
30
use function Shieldon\Firewall\get_session;
31
32
use InvalidArgumentException;
33
use function array_keys;
34
use function define;
35
use function defined;
36
use function is_dir;
37
use function ob_end_clean;
38
use function ob_get_contents;
39
use function ob_start;
40
41
/*
42
 * The template-related functions.
43
 */
44
trait TemplateTrait
45
{
46
    /**
47
     *   Public methods       | Desctiotion
48
     *  ----------------------|---------------------------------------------
49
     *   respond              | Respond the result.
50
     *   setTemplateDirectory | Set the frontend template directory.
51
     *   getJavascript        | Print a JavaScript snippet in the pages.
52
     *  ----------------------|---------------------------------------------
53
     */
54
55
    /**
56
     * Respond the result.
57
     *
58
     * @return ResponseInterface
59
     */
60
    public function respond(): ResponseInterface
61
    {
62
        $response = get_response();
63
64
        $httpStatusCodes = [
65
            kernel::RESPONSE_TEMPORARILY_DENY => [
66
                'type' => 'captcha',
67
                'code' => kernel::HTTP_STATUS_FORBIDDEN,
68
            ],
69
70
            kernel::RESPONSE_LIMIT_SESSION => [
71
                'type' => 'session_limitation',
72
                'code' => kernel::HTTP_STATUS_TOO_MANY_REQUESTS,
73
            ],
74
75
            kernel::RESPONSE_DENY => [
76
                'type' => 'rejection',
77
                'code' => kernel::HTTP_STATUS_BAD_REQUEST,
78
            ],
79
        ];
80
81
        // Nothing happened. Return.
82
        if (empty($httpStatusCodes[$this->result])) {
83
            return $response;
84
        }
85
86
        $type = $httpStatusCodes[$this->result]['type'];
87
        $statusCode = $httpStatusCodes[$this->result]['code'];
88
89
        $viewPath = $this->getTemplate($type);
0 ignored issues
show
Bug introduced by
It seems like getTemplate() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

89
        /** @scrutinizer ignore-call */ 
90
        $viewPath = $this->getTemplate($type);
Loading history...
90
91
        // The language of output UI. It is used on views.
92
        $langCode = get_session()->get('shieldon_ui_lang') ?? 'en';
93
94
        $showOnlineInformation = false;
95
        $showUserInformation = false;
96
        
97
        // Show online session count. It is used on views.
98
        if (!empty($this->properties['display_online_info'])) {
99
            $showOnlineInformation = true;
100
            $onlineinfo = [];
101
102
            $onlineinfo['queue'] = $this->sessionStatus['queue'];
103
            $onlineinfo['count'] = $this->sessionStatus['count'];
104
            $onlineinfo['period'] = $this->sessionLimit['period'];
105
        } 
106
107
        // Show user information such as IP, user-agent, device name.
108
        if (!empty($this->properties['display_user_info'])) {
109
            $showUserInformation = true;
110
            $dialoguserinfo = [];
111
112
            $dialoguserinfo['ip'] = $this->ip;
113
            $dialoguserinfo['rdns'] = $this->rdns;
114
            $dialoguserinfo['user_agent'] = get_request()->getHeaderLine('user-agent');
115
        }
116
117
        // Captcha form
118
        $form = $this->getCurrentUrl();
0 ignored issues
show
Bug introduced by
It seems like getCurrentUrl() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

118
        /** @scrutinizer ignore-call */ 
119
        $form = $this->getCurrentUrl();
Loading history...
119
        $captchas = $this->captcha;
120
121
        $ui = [
122
            'background_image' => '',
123
            'bg_color'         => '#ffffff',
124
            'header_bg_color'  => '#212531',
125
            'header_color'     => '#ffffff',
126
            'shadow_opacity'   => '0.2',
127
        ];
128
129
        foreach (array_keys($ui) as $key) {
130
            if (!empty($this->dialog[$key])) {
131
                $ui[$key] = $this->dialog[$key];
132
            }
133
        }
134
135
        if (!defined('SHIELDON_VIEW')) {
136
            define('SHIELDON_VIEW', true);
137
        }
138
139
        $css = include $this->getTemplate('css/default');
140
141
        ob_start();
142
        include $viewPath;
143
        $output = ob_get_contents();
144
        ob_end_clean();
145
146
        // Remove unused variable notices generated from PHP intelephense.
147
        unset(
148
            $css,
149
            $ui,
150
            $form,
151
            $captchas,
152
            $langCode,
153
            $showOnlineInformation,
154
            $showUserInformation
155
        );
156
157
        $stream = HttpFactory::createStream();
158
        $stream->write($output);
159
        $stream->rewind();
160
161
        return $response
162
            ->withHeader('X-Protected-By', 'shieldon.io')
163
            ->withBody($stream)
164
            ->withStatus($statusCode);
165
    }
166
167
    /**
168
     * Print a JavaScript snippet in your webpages.
169
     * 
170
     * This snippet generate cookie on client's browser,then we check the 
171
     * cookie to identify the client is a rebot or not.
172
     *
173
     * @return string
174
     */
175
    public function getJavascript(): string
176
    {
177
        $tmpCookieName = $this->properties['cookie_name'];
178
        $tmpCookieDomain = $this->properties['cookie_domain'];
179
180
        if (empty($tmpCookieDomain) && get_request()->getHeaderLine('host')) {
181
            $tmpCookieDomain = get_request()->getHeaderLine('host');
182
        }
183
184
        $tmpCookieValue = $this->properties['cookie_value'];
185
186
        $jsString = '
187
            <script>
188
                var d = new Date();
189
                d.setTime(d.getTime()+(60*60*24*30));
190
                document.cookie = "' . $tmpCookieName . '=' . $tmpCookieValue . ';domain=.' . $tmpCookieDomain . ';expires="+d.toUTCString();
191
            </script>
192
        ';
193
194
        return $jsString;
195
    }
196
197
    /**
198
     * Set the frontend template directory.
199
     *
200
     * @param string $directory The directory in where the template files are placed.
201
     *
202
     * @return void
203
     */
204
    public function setTemplateDirectory(string $directory)
205
    {
206
        if (!is_dir($directory)) {
207
            throw new InvalidArgumentException(
208
                'The template directory does not exist.'
209
            );
210
        }
211
        $this->templateDirectory = $directory;
0 ignored issues
show
Bug Best Practice introduced by
The property templateDirectory does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
212
    }
213
}
214