Completed
Push — master ( f8ff86...ec22b1 )
by Henry
03:57
created

Session::__classLoaded()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Divergence\Models\Auth;
3
4
use Divergence\Models\Model;
5
use Divergence\Models\Relations;
6
7
class Session extends Model
8
{
9
    use Relations;
10
11
    // Session configurables
12
    public static $cookieName = 's';
13
    public static $cookieDomain = null;
14
    public static $cookiePath = '/';
15
    public static $cookieSecure = false;
16
    public static $cookieExpires = false;
17
    public static $timeout = 31536000; //3600;
18
19
    // support subclassing
20
    public static $rootClass = __CLASS__;
21
    public static $defaultClass = __CLASS__;
22
    public static $subClasses = [__CLASS__];
23
24
    // ActiveRecord configuration
25
    public static $tableName = 'sessions';
26
    public static $singularNoun = 'session';
27
    public static $pluralNoun = 'sessions';
28
29
    public static $fields = [
30
        'ContextClass' => null,
31
        'ContextID' => null,
32
        'Handle' => [
33
            'unique' => true,
34
        ],
35
        'LastRequest' => [
36
            'type' => 'timestamp',
37
            'notnull' => false,
38
        ],
39
        'LastIP' => [
40
            'type' => 'binary'
41
        ],
42
    ];
43
44
45
    // Session
46
    public static function __classLoaded()
47
    {
48
        parent::__classLoaded();
0 ignored issues
show
Bug introduced by
The method __classLoaded() does not exist on Divergence\Models\Model. It seems like you code against a sub-type of Divergence\Models\Model such as Divergence\Models\Auth\Session or Divergence\Models\Media\Image or Divergence\Models\Media\PDF or Divergence\Models\Media\Audio or Divergence\Models\Media\Video. ( Ignorable by Annotation )

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

48
        parent::/** @scrutinizer ignore-call */ 
49
                __classLoaded();
Loading history...
49
50
        // auto-detect cookie domain
51
        if (empty(static::$cookieDomain)) {
52
            static::$cookieDomain = preg_replace('/^www\.([^.]+\.[^.]+)$/i', '$1', $_SERVER['HTTP_HOST']);
53
        }
54
    }
55
56
57
    public static function getFromRequest($create = true)
58
    {
59
        $sessionData = [
60
            'LastIP' => inet_pton($_SERVER['REMOTE_ADDR']),
61
            'LastRequest' => time(),
62
        ];
63
64
        // try to load from cookie
65
        if (!empty($_COOKIE[static::$cookieName])) {
66
            if ($Session = static::getByHandle($_COOKIE[static::$cookieName])) {
67
                // update session & check expiration
68
                $Session = static::updateSession($Session, $sessionData);
69
            }
70
        }
71
72
        // try to load from any request method
73
        if (empty($Session) && !empty($_REQUEST[static::$cookieName])) {
74
            if ($Session = static::getByHandle($_REQUEST[static::$cookieName])) {
75
                // update session & check expiration
76
                $Session = static::updateSession($Session, $sessionData);
77
            }
78
        }
79
80
        if (!empty($Session)) {
81
            // session found
82
            return $Session;
83
        } elseif ($create) {
84
            // create session
85
            return static::create($sessionData, true);
86
        } else {
87
            // no session available
88
            return false;
89
        }
90
    }
91
92
    public static function updateSession(Session $Session, $sessionData)
93
    {
94
95
        // check timestamp
96
        if ($Session->LastRequest < (time() - static::$timeout)) {
0 ignored issues
show
Bug Best Practice introduced by
The property LastRequest does not exist on Divergence\Models\Auth\Session. Since you implemented __get, consider adding a @property annotation.
Loading history...
97
            $Session->terminate();
98
99
            return false;
100
        } else {
101
            // update session
102
            $Session->setFields($sessionData);
103
            if (function_exists('fastcgi_finish_request')) {
104
                register_shutdown_function(function (&$Session) {
105
                    $Session->save();
106
                }, $Session);
107
            } else {
108
                $Session->save();
109
            }
110
111
            return $Session;
112
        }
113
    }
114
115
    public static function getByHandle($handle)
116
    {
117
        return static::getByField('Handle', $handle, true);
118
    }
119
120
    public function getData()
121
    {
122
        // embed related object(s)
123
        return array_merge(parent::getData(), [
124
            'Person' => $this->Person ? $this->Person->getData() : null,
0 ignored issues
show
Bug Best Practice introduced by
The property Person does not exist on Divergence\Models\Auth\Session. Since you implemented __get, consider adding a @property annotation.
Loading history...
125
        ]);
126
    }
127
128
    public function save($deep = true)
129
    {
130
        // set handle
131
        if (!$this->Handle) {
132
            $this->Handle = static::generateUniqueHandle();
0 ignored issues
show
Bug Best Practice introduced by
The property Handle does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
133
        }
134
135
        // call parent
136
        parent::save($deep);
137
138
        // set cookie
139
        setcookie(
140
            static::$cookieName,
141
            $this->Handle,
142
            static::$cookieExpires ? (time() + static::$cookieExpires) : 0,
143
            static::$cookiePath,
144
            static::$cookieDomain,
145
            static::$cookieSecure
146
        );
147
    }
148
149
    public function terminate()
150
    {
151
        setcookie(static::$cookieName, '', time() - 3600);
152
        unset($_COOKIE[static::$cookieName]);
153
154
        $this->destroy();
155
    }
156
157
158
159
    public static function generateUniqueHandle()
160
    {
161
        do {
162
            $handle = md5(mt_rand(0, mt_getrandmax()));
163
        } while (static::getByHandle($handle));
164
165
        return $handle;
166
    }
167
}
168