Issues (6)

src/Adapters/Session/DatabaseHandler.php (1 issue)

1
<?php
2
/*
3
 * This file is part of the Scrawler package.
4
 *
5
 * (c) Pranjal Pandey <[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
namespace Scrawler\Http\Adapters\Session;
12
13
use Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler;
14
15
/**
16
 * DatabaseHandler class to store session using Arca Orm.
17
 */
18
class DatabaseHandler extends AbstractSessionHandler implements \SessionHandlerInterface
19
{
20
    /**
21
     * Store Database instance.
22
     *
23
     * @var \Scrawler\Database
24
     */
25
    private $db;
26
27
    /**
28
     * Check if gc is called.
29
     */
30
    private bool $gcCalled = false;
31
32
    public function __construct()
33
    {
34
        // @codeCoverageIgnoreStart
35
        if (function_exists('db')) {
36
            $this->db = db();
37
        } else {
38
            throw new \Exception("This adapter requires scrawler\database");
39
        }
40
        // @codeCoverageIgnoreEnd
41
    }
42
43
    #[\Override]
44
    protected function doWrite(string $sessionId, string $data): bool
45
    {
46
        $maxlifetime = (int) \Safe\ini_get('session.gc_maxlifetime');
47
        if (false == $this->db->tableExists('session')) {
48
            $session = $this->db->create('session');
49
        } else {
50
            $session = $this->db->find('session')->where('sessionid  LIKE ?')->setParameter(0, $sessionId)->first();
51
            if (is_null($session)) {
52
                $session = $this->db->create('session');
53
            }
54
        }
55
56
        $session->set('sessionid', $sessionId);
57
        $session->set('session_data', $data);
58
        $session->set('session_expire', time() + $maxlifetime);
59
        $this->db->save($session);
60
61
        return true;
62
    }
63
64
    #[\Override]
65
    protected function doRead(string $sessionId): string
66
    {
67
        $session = $this->db->find('session')->where('sessionid = ? AND session_expire > ?')->setParameters([$sessionId, time()])->first();
68
        if (is_null($session)) {
69
            return '';
70
        }
71
72
        return $session->get('session_data');
73
    }
74
75
    #[\Override]
76
    protected function doDestroy(string $sessionId): bool
77
    {
78
        $session = $this->db->find('session')
79
            ->where('sessionid  LIKE ?')
80
            ->setParameter(0, $sessionId)
81
            ->first();
82
        if (!is_null($session)) {
83
            $this->db->delete($session);
84
        }
85
86
        return true;
87
    }
88
89
    #[\Override]
90
    public function updateTimestamp(string $sessionId, string $data): bool
91
    {
92
        $expiry = (int) \Safe\ini_get('session.gc_maxlifetime');
93
        $session = $this->db->find('session')
94
        ->where('sessionid  LIKE ?')
95
        ->setParameter(0, $sessionId)
96
        ->first();
97
98
        if (!is_null($session)) {
99
            $session->set('session_expire', time() + $expiry);
100
            $this->db->save($session);
101
        }
102
103
        return true;
104
    }
105
106
    #[\Override]
107
    public function gc(int $maxlifetime): int|false
108
    {
109
        $this->gcCalled = true;
110
111
        return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the return type mandated by SessionHandlerInterface::gc() of boolean.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
112
    }
113
114
    // @codeCoverageIgnoreStart
115
    #[\Override]
116
    public function close(): bool
117
    {
118
        if ($this->gcCalled) {
119
            $this->gcCalled = false;
120
121
            $sessions = $this->db->find('session')
122
                ->where('session_expire < ?')
123
                ->setParameter(0, time())
124
                ->get();
125
126
            foreach ($sessions as $session) {
127
                $session->delete();
128
            }
129
        }
130
131
        return true;
132
    }
133
    // @codeCoverageIgnoreEnd
134
}
135