Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Session;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Utility\Crypt;
|
Chris@0
|
6 use Drupal\Core\Database\Connection;
|
Chris@0
|
7 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
Chris@0
|
8 use Drupal\Core\Utility\Error;
|
Chris@0
|
9 use Symfony\Component\HttpFoundation\RequestStack;
|
Chris@0
|
10 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Default session handler.
|
Chris@0
|
14 */
|
Chris@0
|
15 class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {
|
Chris@0
|
16
|
Chris@0
|
17 use DependencySerializationTrait;
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * The request stack.
|
Chris@0
|
21 *
|
Chris@0
|
22 * @var \Symfony\Component\HttpFoundation\RequestStack
|
Chris@0
|
23 */
|
Chris@0
|
24 protected $requestStack;
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * The database connection.
|
Chris@0
|
28 *
|
Chris@0
|
29 * @var \Drupal\Core\Database\Connection
|
Chris@0
|
30 */
|
Chris@0
|
31 protected $connection;
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * Constructs a new SessionHandler instance.
|
Chris@0
|
35 *
|
Chris@0
|
36 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
Chris@0
|
37 * The request stack.
|
Chris@0
|
38 * @param \Drupal\Core\Database\Connection $connection
|
Chris@0
|
39 * The database connection.
|
Chris@0
|
40 */
|
Chris@0
|
41 public function __construct(RequestStack $request_stack, Connection $connection) {
|
Chris@0
|
42 $this->requestStack = $request_stack;
|
Chris@0
|
43 $this->connection = $connection;
|
Chris@0
|
44 }
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * {@inheritdoc}
|
Chris@0
|
48 */
|
Chris@0
|
49 public function open($save_path, $name) {
|
Chris@0
|
50 return TRUE;
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 /**
|
Chris@0
|
54 * {@inheritdoc}
|
Chris@0
|
55 */
|
Chris@0
|
56 public function read($sid) {
|
Chris@0
|
57 $data = '';
|
Chris@0
|
58 if (!empty($sid)) {
|
Chris@0
|
59 // Read the session data from the database.
|
Chris@0
|
60 $query = $this->connection
|
Chris@0
|
61 ->queryRange('SELECT session FROM {sessions} WHERE sid = :sid', 0, 1, [':sid' => Crypt::hashBase64($sid)]);
|
Chris@0
|
62 $data = (string) $query->fetchField();
|
Chris@0
|
63 }
|
Chris@0
|
64 return $data;
|
Chris@0
|
65 }
|
Chris@0
|
66
|
Chris@0
|
67 /**
|
Chris@0
|
68 * {@inheritdoc}
|
Chris@0
|
69 */
|
Chris@0
|
70 public function write($sid, $value) {
|
Chris@0
|
71 // The exception handler is not active at this point, so we need to do it
|
Chris@0
|
72 // manually.
|
Chris@0
|
73 try {
|
Chris@0
|
74 $request = $this->requestStack->getCurrentRequest();
|
Chris@0
|
75 $fields = [
|
Chris@0
|
76 'uid' => $request->getSession()->get('uid', 0),
|
Chris@0
|
77 'hostname' => $request->getClientIP(),
|
Chris@0
|
78 'session' => $value,
|
Chris@0
|
79 'timestamp' => REQUEST_TIME,
|
Chris@0
|
80 ];
|
Chris@0
|
81 $this->connection->merge('sessions')
|
Chris@0
|
82 ->keys(['sid' => Crypt::hashBase64($sid)])
|
Chris@0
|
83 ->fields($fields)
|
Chris@0
|
84 ->execute();
|
Chris@0
|
85 return TRUE;
|
Chris@0
|
86 }
|
Chris@0
|
87 catch (\Exception $exception) {
|
Chris@0
|
88 require_once DRUPAL_ROOT . '/core/includes/errors.inc';
|
Chris@0
|
89 // If we are displaying errors, then do so with no possibility of a
|
Chris@0
|
90 // further uncaught exception being thrown.
|
Chris@0
|
91 if (error_displayable()) {
|
Chris@0
|
92 print '<h1>Uncaught exception thrown in session handler.</h1>';
|
Chris@0
|
93 print '<p>' . Error::renderExceptionSafe($exception) . '</p><hr />';
|
Chris@0
|
94 }
|
Chris@0
|
95 return FALSE;
|
Chris@0
|
96 }
|
Chris@0
|
97 }
|
Chris@0
|
98
|
Chris@0
|
99 /**
|
Chris@0
|
100 * {@inheritdoc}
|
Chris@0
|
101 */
|
Chris@0
|
102 public function close() {
|
Chris@0
|
103 return TRUE;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * {@inheritdoc}
|
Chris@0
|
108 */
|
Chris@0
|
109 public function destroy($sid) {
|
Chris@0
|
110 // Delete session data.
|
Chris@0
|
111 $this->connection->delete('sessions')
|
Chris@0
|
112 ->condition('sid', Crypt::hashBase64($sid))
|
Chris@0
|
113 ->execute();
|
Chris@0
|
114
|
Chris@0
|
115 return TRUE;
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * {@inheritdoc}
|
Chris@0
|
120 */
|
Chris@0
|
121 public function gc($lifetime) {
|
Chris@0
|
122 // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
|
Chris@0
|
123 // value. For example, if you want user sessions to stay in your database
|
Chris@0
|
124 // for three weeks before deleting them, you need to set gc_maxlifetime
|
Chris@0
|
125 // to '1814400'. At that value, only after a user doesn't log in after
|
Chris@0
|
126 // three weeks (1814400 seconds) will his/her session be removed.
|
Chris@0
|
127 $this->connection->delete('sessions')
|
Chris@0
|
128 ->condition('timestamp', REQUEST_TIME - $lifetime, '<')
|
Chris@0
|
129 ->execute();
|
Chris@0
|
130 return TRUE;
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 }
|