Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
Redis
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
4 / 4
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 read
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 saveSession
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 destroy
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * Redis session handler
5 *
6 * Note: Using phpredis extension (see https://github.com/phpredis/phpredis) is
7 * optional, this class use Credis in standalone mode by default
8 *
9 * PHP version 8
10 *
11 * Copyright (C) Moravian Library 2019.
12 * Copyright (C) The National Library of Finland 2023.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2,
16 * as published by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26 *
27 * @category VuFind
28 * @package  Session_Handlers
29 * @author   Veros Kaplan <cpk-dev@mzk.cz>
30 * @author   Josef Moravec <moravec@mzk.cz>
31 * @author   Ere Maijala <ere.maijala@helsinki.fi>
32 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
33 * @link     https://vufind.org/wiki/development:plugins:session_handlers Wiki
34 */
35
36namespace VuFind\Session;
37
38use Laminas\Config\Config;
39
40/**
41 * Redis session handler
42 *
43 * @category VuFind
44 * @package  Session_Handlers
45 * @author   Veros Kaplan <cpk-dev@mzk.cz>
46 * @author   Josef Moravec <moravec@mzk.cz>
47 * @author   Ere Maijala <ere.maijala@helsinki.fi>
48 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
49 * @link     https://vufind.org/wiki/development:plugins:session_handlers Wiki
50 */
51class Redis extends AbstractBase
52{
53    use \VuFind\Service\Feature\RetryTrait;
54
55    /**
56     * Redis connection
57     *
58     * @var \Credis_Client
59     */
60    protected $connection;
61
62    /**
63     * Redis version
64     *
65     * @var int
66     */
67    protected $redisVersion = 3;
68
69    /**
70     * Constructor
71     *
72     * @param \Credis_Client $connection Redis connection object
73     * @param Config         $config     Session configuration ([Session] section of
74     * config.ini)
75     */
76    public function __construct(\Credis_Client $connection, Config $config = null)
77    {
78        parent::__construct($config);
79        $this->redisVersion = (int)($config->redis_version ?? 3);
80        $this->connection = $connection;
81        $this->retryOptions['retryCount'] = 2;
82    }
83
84    /**
85     * Read function must return string value always to make save handler work as
86     * expected. Return empty string if there is no data to read.
87     *
88     * @param string $sessId The session ID to read
89     *
90     * @return string
91     */
92    public function read($sessId): string
93    {
94        return $this->callWithRetry(
95            function () use ($sessId): string {
96                $session = $this->connection->get("vufind_sessions/{$sessId}");
97                return $session !== false ? $session : '';
98            }
99        );
100    }
101
102    /**
103     * Write function that is called when session data is to be saved.
104     *
105     * @param string $sessId The current session ID
106     * @param string $data   The session data to write
107     *
108     * @return bool
109     */
110    protected function saveSession($sessId, $data): bool
111    {
112        return $this->callWithRetry(
113            function () use ($sessId, $data): bool {
114                return $this->connection->setex(
115                    "vufind_sessions/{$sessId}",
116                    $this->lifetime,
117                    $data
118                );
119            }
120        );
121    }
122
123    /**
124     * The destroy handler, this is executed when a session is destroyed with
125     * session_destroy() and takes the session id as its only parameter.
126     *
127     * @param string $sessId The session ID to destroy
128     *
129     * @return bool
130     */
131    public function destroy($sessId): bool
132    {
133        // Perform standard actions required by all session methods:
134        parent::destroy($sessId);
135
136        // Perform Redis-specific cleanup
137        $unlinkMethod = ($this->redisVersion >= 4) ? 'unlink' : 'del';
138        return $this->callWithRetry(
139            function () use ($unlinkMethod, $sessId): bool {
140                $this->connection->$unlinkMethod("vufind_sessions/{$sessId}");
141                return true;
142            }
143        );
144    }
145}