Passed
Push — 2.x ( f3ddab...77ee6f )
by Terry
02:14
created

SessionTrait::getSessionCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
11
declare(strict_types=1);
12
13
namespace Shieldon\Firewall\Kernel;
14
15
use function Shieldon\Firewall\get_session;
16
use function microtime;
17
use function str_replace;
18
use function time;
19
20
/*
21
 * The main functionality for this trait is to limit the online session amount.
22
 */
23
trait SessionTrait
24
{
25
   /**
26
     * Are you willing to limit the online session amount?
27
     *
28
     * @var array
29
     */
30
    protected $sessionLimit = [
31
32
        // How many sessions will be available?
33
        // 0 = no limit.
34
        'count' => 0,
35
36
        // How many minutes will a session be availe to visit?
37
        // 0 = no limit.
38
        'period' => 0, 
39
    ];
40
41
    /**
42
     * Record the online session status.
43
     * This will be enabled when $sessionLimit[count] > 0
44
     *
45
     * This array is recording a live data, not a setting value.
46
     *
47
     * @var array
48
     */
49
    protected $sessionStatus = [
50
51
        // Online session count.
52
        'count' => 0,
53
54
        // Current session order.
55
        'order' => 0,
56
57
        // Current waiting queue.
58
        'queue' => 0,
59
    ];
60
61
    /**
62
     * Get online people count. If enable limitSession.
63
     *
64
     * @return int
65
     */
66
    public function getSessionCount(): int
67
    {
68
        return $this->sessionStatus['count'];
69
    }
70
71
    /**
72
     * Deal with online sessions.
73
     *
74
     * @param int $statusCode The response code.
75
     *
76
     * @return int The response code.
77
     */
78
    protected function sessionHandler($statusCode): int
79
    {
80
        if (self::RESPONSE_ALLOW !== $statusCode) {
0 ignored issues
show
Bug introduced by
The constant Shieldon\Firewall\Kernel...onTrait::RESPONSE_ALLOW was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
81
            return $statusCode;
82
        }
83
84
        // If you don't enable `limit traffic`, ignore the following steps.
85
        if (empty($this->sessionLimit['count'])) {
86
            return self::RESPONSE_ALLOW;
87
88
        } else {
89
90
            // Get the proerties.
91
            $limit = (int) ($this->sessionLimit['count'] ?? 0);
92
            $period = (int) ($this->sessionLimit['period'] ?? 300);
93
            $now = time();
94
95
            $sessionData = $this->driver->getAll('session');
96
            $sessionPools = [];
97
98
            $i = 1;
99
            $sessionOrder = 0;
100
101
            if (!empty($sessionData)) {
102
                foreach ($sessionData as $v) {
103
                    $sessionPools[] = $v['id'];
104
                    $lasttime = (int) $v['time'];
105
    
106
                    if (get_session()->get('id') === $v['id']) {
107
                        $sessionOrder = $i;
108
                    }
109
    
110
                    // Remove session if it expires.
111
                    if ($now - $lasttime > $period) {
112
                        $this->driver->delete($v['id'], 'session');
113
                    }
114
                    $i++;
115
                }
116
117
                if (0 === $sessionOrder) {
118
                    $sessionOrder = $i;
119
                }
120
            } else {
121
                $sessionOrder = 0;
122
            }
123
124
            // Count the online sessions.
125
            $this->sessionStatus['count'] = count($sessionPools);
126
            $this->sessionStatus['order'] = $sessionOrder;
127
            $this->sessionStatus['queue'] = $sessionOrder - $limit;
128
129
            if (!in_array(get_session()->get('id'), $sessionPools)) {
130
                $this->sessionStatus['count']++;
131
132
                // New session, record this data.
133
                $data['id'] = get_session()->get('id');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
134
                $data['ip'] = $this->ip;
135
                $data['time'] = $now;
136
137
                $microtimesamp = explode(' ', microtime());
138
                $microtimesamp = $microtimesamp[1] . str_replace('0.', '', $microtimesamp[0]);
139
                $data['microtimesamp'] = $microtimesamp;
140
141
                $this->driver->save(get_session()->get('id'), $data, 'session');
142
            }
143
144
            // Online session count reached the limit. So return RESPONSE_LIMIT_SESSION response code.
145
            if ($sessionOrder >= $limit) {
146
                return self::RESPONSE_LIMIT_SESSION;
0 ignored issues
show
Bug introduced by
The constant Shieldon\Firewall\Kernel...:RESPONSE_LIMIT_SESSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
147
            }
148
        }
149
150
        return self::RESPONSE_ALLOW;
151
    }
152
153
154
155
    // @codeCoverageIgnoreStart
156
157
    /**
158
     * For testing propose.
159
     *
160
     * @param string $sessionId
161
     *
162
     * @return void
163
     */
164
    protected function setSessionId(string $sessionId = ''): void
165
    {
166
        if ('' !== $sessionId) {
167
            get_session()->set('id', $sessionId);
168
        }
169
    }
170
}
171